1 /* 2 * Copyright 2008 Rodrigo Kumpera 3 * Copyright 2008 Andr Tupinamb 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 Red Hat not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. Red Hat makes no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * 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 * Author: Rodrigo Kumpera (kumpera (at) gmail.com) 25 * Andr Tupinamb (andrelrt (at) gmail.com) 26 * 27 * Based on work by Owen Taylor and Sren Sandmann 28 */ 29 #ifdef HAVE_CONFIG_H 30 #include <config.h> 31 #endif 32 33 #include <xmmintrin.h> /* for _mm_shuffle_pi16 and _MM_SHUFFLE */ 34 #include <emmintrin.h> /* for SSE2 intrinsics */ 35 #include "pixman-private.h" 36 #include "pixman-combine32.h" 37 #include "pixman-inlines.h" 38 39 static __m128i mask_0080; 40 static __m128i mask_00ff; 41 static __m128i mask_0101; 42 static __m128i mask_ffff; 43 static __m128i mask_ff000000; 44 static __m128i mask_alpha; 45 46 static __m128i mask_565_r; 47 static __m128i mask_565_g1, mask_565_g2; 48 static __m128i mask_565_b; 49 static __m128i mask_red; 50 static __m128i mask_green; 51 static __m128i mask_blue; 52 53 static __m128i mask_565_fix_rb; 54 static __m128i mask_565_fix_g; 55 56 static __m128i mask_565_rb; 57 static __m128i mask_565_pack_multiplier; 58 59 static force_inline __m128i 60 unpack_32_1x128 (uint32_t data) 61 { 62 return _mm_unpacklo_epi8 (_mm_cvtsi32_si128 (data), _mm_setzero_si128 ()); 63 } 64 65 static force_inline void 66 unpack_128_2x128 (__m128i data, __m128i* data_lo, __m128i* data_hi) 67 { 68 *data_lo = _mm_unpacklo_epi8 (data, _mm_setzero_si128 ()); 69 *data_hi = _mm_unpackhi_epi8 (data, _mm_setzero_si128 ()); 70 } 71 72 static force_inline __m128i 73 unpack_565_to_8888 (__m128i lo) 74 { 75 __m128i r, g, b, rb, t; 76 77 r = _mm_and_si128 (_mm_slli_epi32 (lo, 8), mask_red); 78 g = _mm_and_si128 (_mm_slli_epi32 (lo, 5), mask_green); 79 b = _mm_and_si128 (_mm_slli_epi32 (lo, 3), mask_blue); 80 81 rb = _mm_or_si128 (r, b); 82 t = _mm_and_si128 (rb, mask_565_fix_rb); 83 t = _mm_srli_epi32 (t, 5); 84 rb = _mm_or_si128 (rb, t); 85 86 t = _mm_and_si128 (g, mask_565_fix_g); 87 t = _mm_srli_epi32 (t, 6); 88 g = _mm_or_si128 (g, t); 89 90 return _mm_or_si128 (rb, g); 91 } 92 93 static force_inline void 94 unpack_565_128_4x128 (__m128i data, 95 __m128i* data0, 96 __m128i* data1, 97 __m128i* data2, 98 __m128i* data3) 99 { 100 __m128i lo, hi; 101 102 lo = _mm_unpacklo_epi16 (data, _mm_setzero_si128 ()); 103 hi = _mm_unpackhi_epi16 (data, _mm_setzero_si128 ()); 104 105 lo = unpack_565_to_8888 (lo); 106 hi = unpack_565_to_8888 (hi); 107 108 unpack_128_2x128 (lo, data0, data1); 109 unpack_128_2x128 (hi, data2, data3); 110 } 111 112 static force_inline uint16_t 113 pack_565_32_16 (uint32_t pixel) 114 { 115 return (uint16_t) (((pixel >> 8) & 0xf800) | 116 ((pixel >> 5) & 0x07e0) | 117 ((pixel >> 3) & 0x001f)); 118 } 119 120 static force_inline __m128i 121 pack_2x128_128 (__m128i lo, __m128i hi) 122 { 123 return _mm_packus_epi16 (lo, hi); 124 } 125 126 static force_inline __m128i 127 pack_565_2packedx128_128 (__m128i lo, __m128i hi) 128 { 129 __m128i rb0 = _mm_and_si128 (lo, mask_565_rb); 130 __m128i rb1 = _mm_and_si128 (hi, mask_565_rb); 131 132 __m128i t0 = _mm_madd_epi16 (rb0, mask_565_pack_multiplier); 133 __m128i t1 = _mm_madd_epi16 (rb1, mask_565_pack_multiplier); 134 135 __m128i g0 = _mm_and_si128 (lo, mask_green); 136 __m128i g1 = _mm_and_si128 (hi, mask_green); 137 138 t0 = _mm_or_si128 (t0, g0); 139 t1 = _mm_or_si128 (t1, g1); 140 141 /* Simulates _mm_packus_epi32 */ 142 t0 = _mm_slli_epi32 (t0, 16 - 5); 143 t1 = _mm_slli_epi32 (t1, 16 - 5); 144 t0 = _mm_srai_epi32 (t0, 16); 145 t1 = _mm_srai_epi32 (t1, 16); 146 return _mm_packs_epi32 (t0, t1); 147 } 148 149 static force_inline __m128i 150 pack_565_2x128_128 (__m128i lo, __m128i hi) 151 { 152 __m128i data; 153 __m128i r, g1, g2, b; 154 155 data = pack_2x128_128 (lo, hi); 156 157 r = _mm_and_si128 (data, mask_565_r); 158 g1 = _mm_and_si128 (_mm_slli_epi32 (data, 3), mask_565_g1); 159 g2 = _mm_and_si128 (_mm_srli_epi32 (data, 5), mask_565_g2); 160 b = _mm_and_si128 (_mm_srli_epi32 (data, 3), mask_565_b); 161 162 return _mm_or_si128 (_mm_or_si128 (_mm_or_si128 (r, g1), g2), b); 163 } 164 165 static force_inline __m128i 166 pack_565_4x128_128 (__m128i* xmm0, __m128i* xmm1, __m128i* xmm2, __m128i* xmm3) 167 { 168 return _mm_packus_epi16 (pack_565_2x128_128 (*xmm0, *xmm1), 169 pack_565_2x128_128 (*xmm2, *xmm3)); 170 } 171 172 static force_inline int 173 is_opaque (__m128i x) 174 { 175 __m128i ffs = _mm_cmpeq_epi8 (x, x); 176 177 return (_mm_movemask_epi8 (_mm_cmpeq_epi8 (x, ffs)) & 0x8888) == 0x8888; 178 } 179 180 static force_inline int 181 is_zero (__m128i x) 182 { 183 return _mm_movemask_epi8 ( 184 _mm_cmpeq_epi8 (x, _mm_setzero_si128 ())) == 0xffff; 185 } 186 187 static force_inline int 188 is_transparent (__m128i x) 189 { 190 return (_mm_movemask_epi8 ( 191 _mm_cmpeq_epi8 (x, _mm_setzero_si128 ())) & 0x8888) == 0x8888; 192 } 193 194 static force_inline __m128i 195 expand_pixel_32_1x128 (uint32_t data) 196 { 197 return _mm_shuffle_epi32 (unpack_32_1x128 (data), _MM_SHUFFLE (1, 0, 1, 0)); 198 } 199 200 static force_inline __m128i 201 expand_alpha_1x128 (__m128i data) 202 { 203 return _mm_shufflehi_epi16 (_mm_shufflelo_epi16 (data, 204 _MM_SHUFFLE (3, 3, 3, 3)), 205 _MM_SHUFFLE (3, 3, 3, 3)); 206 } 207 208 static force_inline void 209 expand_alpha_2x128 (__m128i data_lo, 210 __m128i data_hi, 211 __m128i* alpha_lo, 212 __m128i* alpha_hi) 213 { 214 __m128i lo, hi; 215 216 lo = _mm_shufflelo_epi16 (data_lo, _MM_SHUFFLE (3, 3, 3, 3)); 217 hi = _mm_shufflelo_epi16 (data_hi, _MM_SHUFFLE (3, 3, 3, 3)); 218 219 *alpha_lo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE (3, 3, 3, 3)); 220 *alpha_hi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE (3, 3, 3, 3)); 221 } 222 223 static force_inline void 224 expand_alpha_rev_2x128 (__m128i data_lo, 225 __m128i data_hi, 226 __m128i* alpha_lo, 227 __m128i* alpha_hi) 228 { 229 __m128i lo, hi; 230 231 lo = _mm_shufflelo_epi16 (data_lo, _MM_SHUFFLE (0, 0, 0, 0)); 232 hi = _mm_shufflelo_epi16 (data_hi, _MM_SHUFFLE (0, 0, 0, 0)); 233 *alpha_lo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE (0, 0, 0, 0)); 234 *alpha_hi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE (0, 0, 0, 0)); 235 } 236 237 static force_inline void 238 pix_multiply_2x128 (__m128i* data_lo, 239 __m128i* data_hi, 240 __m128i* alpha_lo, 241 __m128i* alpha_hi, 242 __m128i* ret_lo, 243 __m128i* ret_hi) 244 { 245 __m128i lo, hi; 246 247 lo = _mm_mullo_epi16 (*data_lo, *alpha_lo); 248 hi = _mm_mullo_epi16 (*data_hi, *alpha_hi); 249 lo = _mm_adds_epu16 (lo, mask_0080); 250 hi = _mm_adds_epu16 (hi, mask_0080); 251 *ret_lo = _mm_mulhi_epu16 (lo, mask_0101); 252 *ret_hi = _mm_mulhi_epu16 (hi, mask_0101); 253 } 254 255 static force_inline void 256 pix_add_multiply_2x128 (__m128i* src_lo, 257 __m128i* src_hi, 258 __m128i* alpha_dst_lo, 259 __m128i* alpha_dst_hi, 260 __m128i* dst_lo, 261 __m128i* dst_hi, 262 __m128i* alpha_src_lo, 263 __m128i* alpha_src_hi, 264 __m128i* ret_lo, 265 __m128i* ret_hi) 266 { 267 __m128i t1_lo, t1_hi; 268 __m128i t2_lo, t2_hi; 269 270 pix_multiply_2x128 (src_lo, src_hi, alpha_dst_lo, alpha_dst_hi, &t1_lo, &t1_hi); 271 pix_multiply_2x128 (dst_lo, dst_hi, alpha_src_lo, alpha_src_hi, &t2_lo, &t2_hi); 272 273 *ret_lo = _mm_adds_epu8 (t1_lo, t2_lo); 274 *ret_hi = _mm_adds_epu8 (t1_hi, t2_hi); 275 } 276 277 static force_inline void 278 negate_2x128 (__m128i data_lo, 279 __m128i data_hi, 280 __m128i* neg_lo, 281 __m128i* neg_hi) 282 { 283 *neg_lo = _mm_xor_si128 (data_lo, mask_00ff); 284 *neg_hi = _mm_xor_si128 (data_hi, mask_00ff); 285 } 286 287 static force_inline void 288 invert_colors_2x128 (__m128i data_lo, 289 __m128i data_hi, 290 __m128i* inv_lo, 291 __m128i* inv_hi) 292 { 293 __m128i lo, hi; 294 295 lo = _mm_shufflelo_epi16 (data_lo, _MM_SHUFFLE (3, 0, 1, 2)); 296 hi = _mm_shufflelo_epi16 (data_hi, _MM_SHUFFLE (3, 0, 1, 2)); 297 *inv_lo = _mm_shufflehi_epi16 (lo, _MM_SHUFFLE (3, 0, 1, 2)); 298 *inv_hi = _mm_shufflehi_epi16 (hi, _MM_SHUFFLE (3, 0, 1, 2)); 299 } 300 301 static force_inline void 302 over_2x128 (__m128i* src_lo, 303 __m128i* src_hi, 304 __m128i* alpha_lo, 305 __m128i* alpha_hi, 306 __m128i* dst_lo, 307 __m128i* dst_hi) 308 { 309 __m128i t1, t2; 310 311 negate_2x128 (*alpha_lo, *alpha_hi, &t1, &t2); 312 313 pix_multiply_2x128 (dst_lo, dst_hi, &t1, &t2, dst_lo, dst_hi); 314 315 *dst_lo = _mm_adds_epu8 (*src_lo, *dst_lo); 316 *dst_hi = _mm_adds_epu8 (*src_hi, *dst_hi); 317 } 318 319 static force_inline void 320 over_rev_non_pre_2x128 (__m128i src_lo, 321 __m128i src_hi, 322 __m128i* dst_lo, 323 __m128i* dst_hi) 324 { 325 __m128i lo, hi; 326 __m128i alpha_lo, alpha_hi; 327 328 expand_alpha_2x128 (src_lo, src_hi, &alpha_lo, &alpha_hi); 329 330 lo = _mm_or_si128 (alpha_lo, mask_alpha); 331 hi = _mm_or_si128 (alpha_hi, mask_alpha); 332 333 invert_colors_2x128 (src_lo, src_hi, &src_lo, &src_hi); 334 335 pix_multiply_2x128 (&src_lo, &src_hi, &lo, &hi, &lo, &hi); 336 337 over_2x128 (&lo, &hi, &alpha_lo, &alpha_hi, dst_lo, dst_hi); 338 } 339 340 static force_inline void 341 in_over_2x128 (__m128i* src_lo, 342 __m128i* src_hi, 343 __m128i* alpha_lo, 344 __m128i* alpha_hi, 345 __m128i* mask_lo, 346 __m128i* mask_hi, 347 __m128i* dst_lo, 348 __m128i* dst_hi) 349 { 350 __m128i s_lo, s_hi; 351 __m128i a_lo, a_hi; 352 353 pix_multiply_2x128 (src_lo, src_hi, mask_lo, mask_hi, &s_lo, &s_hi); 354 pix_multiply_2x128 (alpha_lo, alpha_hi, mask_lo, mask_hi, &a_lo, &a_hi); 355 356 over_2x128 (&s_lo, &s_hi, &a_lo, &a_hi, dst_lo, dst_hi); 357 } 358 359 /* load 4 pixels from a 16-byte boundary aligned address */ 360 static force_inline __m128i 361 load_128_aligned (__m128i* src) 362 { 363 return _mm_load_si128 (src); 364 } 365 366 /* load 4 pixels from a unaligned address */ 367 static force_inline __m128i 368 load_128_unaligned (const __m128i* src) 369 { 370 return _mm_loadu_si128 (src); 371 } 372 373 /* save 4 pixels using Write Combining memory on a 16-byte 374 * boundary aligned address 375 */ 376 static force_inline void 377 save_128_write_combining (__m128i* dst, 378 __m128i data) 379 { 380 _mm_stream_si128 (dst, data); 381 } 382 383 /* save 4 pixels on a 16-byte boundary aligned address */ 384 static force_inline void 385 save_128_aligned (__m128i* dst, 386 __m128i data) 387 { 388 _mm_store_si128 (dst, data); 389 } 390 391 /* save 4 pixels on a unaligned address */ 392 static force_inline void 393 save_128_unaligned (__m128i* dst, 394 __m128i data) 395 { 396 _mm_storeu_si128 (dst, data); 397 } 398 399 static force_inline __m128i 400 load_32_1x128 (uint32_t data) 401 { 402 return _mm_cvtsi32_si128 (data); 403 } 404 405 static force_inline __m128i 406 expand_alpha_rev_1x128 (__m128i data) 407 { 408 return _mm_shufflelo_epi16 (data, _MM_SHUFFLE (0, 0, 0, 0)); 409 } 410 411 static force_inline __m128i 412 expand_pixel_8_1x128 (uint8_t data) 413 { 414 return _mm_shufflelo_epi16 ( 415 unpack_32_1x128 ((uint32_t)data), _MM_SHUFFLE (0, 0, 0, 0)); 416 } 417 418 static force_inline __m128i 419 pix_multiply_1x128 (__m128i data, 420 __m128i alpha) 421 { 422 return _mm_mulhi_epu16 (_mm_adds_epu16 (_mm_mullo_epi16 (data, alpha), 423 mask_0080), 424 mask_0101); 425 } 426 427 static force_inline __m128i 428 pix_add_multiply_1x128 (__m128i* src, 429 __m128i* alpha_dst, 430 __m128i* dst, 431 __m128i* alpha_src) 432 { 433 __m128i t1 = pix_multiply_1x128 (*src, *alpha_dst); 434 __m128i t2 = pix_multiply_1x128 (*dst, *alpha_src); 435 436 return _mm_adds_epu8 (t1, t2); 437 } 438 439 static force_inline __m128i 440 negate_1x128 (__m128i data) 441 { 442 return _mm_xor_si128 (data, mask_00ff); 443 } 444 445 static force_inline __m128i 446 invert_colors_1x128 (__m128i data) 447 { 448 return _mm_shufflelo_epi16 (data, _MM_SHUFFLE (3, 0, 1, 2)); 449 } 450 451 static force_inline __m128i 452 over_1x128 (__m128i src, __m128i alpha, __m128i dst) 453 { 454 return _mm_adds_epu8 (src, pix_multiply_1x128 (dst, negate_1x128 (alpha))); 455 } 456 457 static force_inline __m128i 458 in_over_1x128 (__m128i* src, __m128i* alpha, __m128i* mask, __m128i* dst) 459 { 460 return over_1x128 (pix_multiply_1x128 (*src, *mask), 461 pix_multiply_1x128 (*alpha, *mask), 462 *dst); 463 } 464 465 static force_inline __m128i 466 over_rev_non_pre_1x128 (__m128i src, __m128i dst) 467 { 468 __m128i alpha = expand_alpha_1x128 (src); 469 470 return over_1x128 (pix_multiply_1x128 (invert_colors_1x128 (src), 471 _mm_or_si128 (alpha, mask_alpha)), 472 alpha, 473 dst); 474 } 475 476 static force_inline uint32_t 477 pack_1x128_32 (__m128i data) 478 { 479 return _mm_cvtsi128_si32 (_mm_packus_epi16 (data, _mm_setzero_si128 ())); 480 } 481 482 static force_inline __m128i 483 expand565_16_1x128 (uint16_t pixel) 484 { 485 __m128i m = _mm_cvtsi32_si128 (pixel); 486 487 m = unpack_565_to_8888 (m); 488 489 return _mm_unpacklo_epi8 (m, _mm_setzero_si128 ()); 490 } 491 492 static force_inline uint32_t 493 core_combine_over_u_pixel_sse2 (uint32_t src, uint32_t dst) 494 { 495 uint8_t a; 496 __m128i xmms; 497 498 a = src >> 24; 499 500 if (a == 0xff) 501 { 502 return src; 503 } 504 else if (src) 505 { 506 xmms = unpack_32_1x128 (src); 507 return pack_1x128_32 ( 508 over_1x128 (xmms, expand_alpha_1x128 (xmms), 509 unpack_32_1x128 (dst))); 510 } 511 512 return dst; 513 } 514 515 static force_inline uint32_t 516 combine1 (const uint32_t *ps, const uint32_t *pm) 517 { 518 uint32_t s = *ps; 519 520 if (pm) 521 { 522 __m128i ms, mm; 523 524 mm = unpack_32_1x128 (*pm); 525 mm = expand_alpha_1x128 (mm); 526 527 ms = unpack_32_1x128 (s); 528 ms = pix_multiply_1x128 (ms, mm); 529 530 s = pack_1x128_32 (ms); 531 } 532 533 return s; 534 } 535 536 static force_inline __m128i 537 combine4 (const __m128i *ps, const __m128i *pm) 538 { 539 __m128i xmm_src_lo, xmm_src_hi; 540 __m128i xmm_msk_lo, xmm_msk_hi; 541 __m128i s; 542 543 if (pm) 544 { 545 xmm_msk_lo = load_128_unaligned (pm); 546 547 if (is_transparent (xmm_msk_lo)) 548 return _mm_setzero_si128 (); 549 } 550 551 s = load_128_unaligned (ps); 552 553 if (pm) 554 { 555 unpack_128_2x128 (s, &xmm_src_lo, &xmm_src_hi); 556 unpack_128_2x128 (xmm_msk_lo, &xmm_msk_lo, &xmm_msk_hi); 557 558 expand_alpha_2x128 (xmm_msk_lo, xmm_msk_hi, &xmm_msk_lo, &xmm_msk_hi); 559 560 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 561 &xmm_msk_lo, &xmm_msk_hi, 562 &xmm_src_lo, &xmm_src_hi); 563 564 s = pack_2x128_128 (xmm_src_lo, xmm_src_hi); 565 } 566 567 return s; 568 } 569 570 static force_inline void 571 core_combine_over_u_sse2_mask (uint32_t * pd, 572 const uint32_t* ps, 573 const uint32_t* pm, 574 int w) 575 { 576 uint32_t s, d; 577 578 /* Align dst on a 16-byte boundary */ 579 while (w && ((uintptr_t)pd & 15)) 580 { 581 d = *pd; 582 s = combine1 (ps, pm); 583 584 if (s) 585 *pd = core_combine_over_u_pixel_sse2 (s, d); 586 pd++; 587 ps++; 588 pm++; 589 w--; 590 } 591 592 while (w >= 4) 593 { 594 __m128i mask = load_128_unaligned ((__m128i *)pm); 595 596 if (!is_zero (mask)) 597 { 598 __m128i src; 599 __m128i src_hi, src_lo; 600 __m128i mask_hi, mask_lo; 601 __m128i alpha_hi, alpha_lo; 602 603 src = load_128_unaligned ((__m128i *)ps); 604 605 if (is_opaque (_mm_and_si128 (src, mask))) 606 { 607 save_128_aligned ((__m128i *)pd, src); 608 } 609 else 610 { 611 __m128i dst = load_128_aligned ((__m128i *)pd); 612 __m128i dst_hi, dst_lo; 613 614 unpack_128_2x128 (mask, &mask_lo, &mask_hi); 615 unpack_128_2x128 (src, &src_lo, &src_hi); 616 617 expand_alpha_2x128 (mask_lo, mask_hi, &mask_lo, &mask_hi); 618 pix_multiply_2x128 (&src_lo, &src_hi, 619 &mask_lo, &mask_hi, 620 &src_lo, &src_hi); 621 622 unpack_128_2x128 (dst, &dst_lo, &dst_hi); 623 624 expand_alpha_2x128 (src_lo, src_hi, 625 &alpha_lo, &alpha_hi); 626 627 over_2x128 (&src_lo, &src_hi, &alpha_lo, &alpha_hi, 628 &dst_lo, &dst_hi); 629 630 save_128_aligned ( 631 (__m128i *)pd, 632 pack_2x128_128 (dst_lo, dst_hi)); 633 } 634 } 635 636 pm += 4; 637 ps += 4; 638 pd += 4; 639 w -= 4; 640 } 641 while (w) 642 { 643 d = *pd; 644 s = combine1 (ps, pm); 645 646 if (s) 647 *pd = core_combine_over_u_pixel_sse2 (s, d); 648 pd++; 649 ps++; 650 pm++; 651 652 w--; 653 } 654 } 655 656 static force_inline void 657 core_combine_over_u_sse2_no_mask (uint32_t * pd, 658 const uint32_t* ps, 659 int w) 660 { 661 uint32_t s, d; 662 663 /* Align dst on a 16-byte boundary */ 664 while (w && ((uintptr_t)pd & 15)) 665 { 666 d = *pd; 667 s = *ps; 668 669 if (s) 670 *pd = core_combine_over_u_pixel_sse2 (s, d); 671 pd++; 672 ps++; 673 w--; 674 } 675 676 while (w >= 4) 677 { 678 __m128i src; 679 __m128i src_hi, src_lo, dst_hi, dst_lo; 680 __m128i alpha_hi, alpha_lo; 681 682 src = load_128_unaligned ((__m128i *)ps); 683 684 if (!is_zero (src)) 685 { 686 if (is_opaque (src)) 687 { 688 save_128_aligned ((__m128i *)pd, src); 689 } 690 else 691 { 692 __m128i dst = load_128_aligned ((__m128i *)pd); 693 694 unpack_128_2x128 (src, &src_lo, &src_hi); 695 unpack_128_2x128 (dst, &dst_lo, &dst_hi); 696 697 expand_alpha_2x128 (src_lo, src_hi, 698 &alpha_lo, &alpha_hi); 699 over_2x128 (&src_lo, &src_hi, &alpha_lo, &alpha_hi, 700 &dst_lo, &dst_hi); 701 702 save_128_aligned ( 703 (__m128i *)pd, 704 pack_2x128_128 (dst_lo, dst_hi)); 705 } 706 } 707 708 ps += 4; 709 pd += 4; 710 w -= 4; 711 } 712 while (w) 713 { 714 d = *pd; 715 s = *ps; 716 717 if (s) 718 *pd = core_combine_over_u_pixel_sse2 (s, d); 719 pd++; 720 ps++; 721 722 w--; 723 } 724 } 725 726 static force_inline void 727 sse2_combine_over_u (pixman_implementation_t *imp, 728 pixman_op_t op, 729 uint32_t * pd, 730 const uint32_t * ps, 731 const uint32_t * pm, 732 int w) 733 { 734 if (pm) 735 core_combine_over_u_sse2_mask (pd, ps, pm, w); 736 else 737 core_combine_over_u_sse2_no_mask (pd, ps, w); 738 } 739 740 static void 741 sse2_combine_over_reverse_u (pixman_implementation_t *imp, 742 pixman_op_t op, 743 uint32_t * pd, 744 const uint32_t * ps, 745 const uint32_t * pm, 746 int w) 747 { 748 uint32_t s, d; 749 750 __m128i xmm_dst_lo, xmm_dst_hi; 751 __m128i xmm_src_lo, xmm_src_hi; 752 __m128i xmm_alpha_lo, xmm_alpha_hi; 753 754 /* Align dst on a 16-byte boundary */ 755 while (w && 756 ((uintptr_t)pd & 15)) 757 { 758 d = *pd; 759 s = combine1 (ps, pm); 760 761 *pd++ = core_combine_over_u_pixel_sse2 (d, s); 762 w--; 763 ps++; 764 if (pm) 765 pm++; 766 } 767 768 while (w >= 4) 769 { 770 /* I'm loading unaligned because I'm not sure 771 * about the address alignment. 772 */ 773 xmm_src_hi = combine4 ((__m128i*)ps, (__m128i*)pm); 774 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 775 776 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 777 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 778 779 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 780 &xmm_alpha_lo, &xmm_alpha_hi); 781 782 over_2x128 (&xmm_dst_lo, &xmm_dst_hi, 783 &xmm_alpha_lo, &xmm_alpha_hi, 784 &xmm_src_lo, &xmm_src_hi); 785 786 /* rebuid the 4 pixel data and save*/ 787 save_128_aligned ((__m128i*)pd, 788 pack_2x128_128 (xmm_src_lo, xmm_src_hi)); 789 790 w -= 4; 791 ps += 4; 792 pd += 4; 793 794 if (pm) 795 pm += 4; 796 } 797 798 while (w) 799 { 800 d = *pd; 801 s = combine1 (ps, pm); 802 803 *pd++ = core_combine_over_u_pixel_sse2 (d, s); 804 ps++; 805 w--; 806 if (pm) 807 pm++; 808 } 809 } 810 811 static force_inline uint32_t 812 core_combine_in_u_pixel_sse2 (uint32_t src, uint32_t dst) 813 { 814 uint32_t maska = src >> 24; 815 816 if (maska == 0) 817 { 818 return 0; 819 } 820 else if (maska != 0xff) 821 { 822 return pack_1x128_32 ( 823 pix_multiply_1x128 (unpack_32_1x128 (dst), 824 expand_alpha_1x128 (unpack_32_1x128 (src)))); 825 } 826 827 return dst; 828 } 829 830 static void 831 sse2_combine_in_u (pixman_implementation_t *imp, 832 pixman_op_t op, 833 uint32_t * pd, 834 const uint32_t * ps, 835 const uint32_t * pm, 836 int w) 837 { 838 uint32_t s, d; 839 840 __m128i xmm_src_lo, xmm_src_hi; 841 __m128i xmm_dst_lo, xmm_dst_hi; 842 843 while (w && ((uintptr_t)pd & 15)) 844 { 845 s = combine1 (ps, pm); 846 d = *pd; 847 848 *pd++ = core_combine_in_u_pixel_sse2 (d, s); 849 w--; 850 ps++; 851 if (pm) 852 pm++; 853 } 854 855 while (w >= 4) 856 { 857 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 858 xmm_src_hi = combine4 ((__m128i*) ps, (__m128i*) pm); 859 860 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 861 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 862 863 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 864 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 865 &xmm_dst_lo, &xmm_dst_hi, 866 &xmm_dst_lo, &xmm_dst_hi); 867 868 save_128_aligned ((__m128i*)pd, 869 pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 870 871 ps += 4; 872 pd += 4; 873 w -= 4; 874 if (pm) 875 pm += 4; 876 } 877 878 while (w) 879 { 880 s = combine1 (ps, pm); 881 d = *pd; 882 883 *pd++ = core_combine_in_u_pixel_sse2 (d, s); 884 w--; 885 ps++; 886 if (pm) 887 pm++; 888 } 889 } 890 891 static void 892 sse2_combine_in_reverse_u (pixman_implementation_t *imp, 893 pixman_op_t op, 894 uint32_t * pd, 895 const uint32_t * ps, 896 const uint32_t * pm, 897 int w) 898 { 899 uint32_t s, d; 900 901 __m128i xmm_src_lo, xmm_src_hi; 902 __m128i xmm_dst_lo, xmm_dst_hi; 903 904 while (w && ((uintptr_t)pd & 15)) 905 { 906 s = combine1 (ps, pm); 907 d = *pd; 908 909 *pd++ = core_combine_in_u_pixel_sse2 (s, d); 910 ps++; 911 w--; 912 if (pm) 913 pm++; 914 } 915 916 while (w >= 4) 917 { 918 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 919 xmm_src_hi = combine4 ((__m128i*) ps, (__m128i*)pm); 920 921 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 922 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 923 924 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 925 pix_multiply_2x128 (&xmm_dst_lo, &xmm_dst_hi, 926 &xmm_src_lo, &xmm_src_hi, 927 &xmm_dst_lo, &xmm_dst_hi); 928 929 save_128_aligned ( 930 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 931 932 ps += 4; 933 pd += 4; 934 w -= 4; 935 if (pm) 936 pm += 4; 937 } 938 939 while (w) 940 { 941 s = combine1 (ps, pm); 942 d = *pd; 943 944 *pd++ = core_combine_in_u_pixel_sse2 (s, d); 945 w--; 946 ps++; 947 if (pm) 948 pm++; 949 } 950 } 951 952 static void 953 sse2_combine_out_reverse_u (pixman_implementation_t *imp, 954 pixman_op_t op, 955 uint32_t * pd, 956 const uint32_t * ps, 957 const uint32_t * pm, 958 int w) 959 { 960 while (w && ((uintptr_t)pd & 15)) 961 { 962 uint32_t s = combine1 (ps, pm); 963 uint32_t d = *pd; 964 965 *pd++ = pack_1x128_32 ( 966 pix_multiply_1x128 ( 967 unpack_32_1x128 (d), negate_1x128 ( 968 expand_alpha_1x128 (unpack_32_1x128 (s))))); 969 970 if (pm) 971 pm++; 972 ps++; 973 w--; 974 } 975 976 while (w >= 4) 977 { 978 __m128i xmm_src_lo, xmm_src_hi; 979 __m128i xmm_dst_lo, xmm_dst_hi; 980 981 xmm_src_hi = combine4 ((__m128i*)ps, (__m128i*)pm); 982 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 983 984 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 985 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 986 987 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 988 negate_2x128 (xmm_src_lo, xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 989 990 pix_multiply_2x128 (&xmm_dst_lo, &xmm_dst_hi, 991 &xmm_src_lo, &xmm_src_hi, 992 &xmm_dst_lo, &xmm_dst_hi); 993 994 save_128_aligned ( 995 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 996 997 ps += 4; 998 pd += 4; 999 if (pm) 1000 pm += 4; 1001 1002 w -= 4; 1003 } 1004 1005 while (w) 1006 { 1007 uint32_t s = combine1 (ps, pm); 1008 uint32_t d = *pd; 1009 1010 *pd++ = pack_1x128_32 ( 1011 pix_multiply_1x128 ( 1012 unpack_32_1x128 (d), negate_1x128 ( 1013 expand_alpha_1x128 (unpack_32_1x128 (s))))); 1014 ps++; 1015 if (pm) 1016 pm++; 1017 w--; 1018 } 1019 } 1020 1021 static void 1022 sse2_combine_out_u (pixman_implementation_t *imp, 1023 pixman_op_t op, 1024 uint32_t * pd, 1025 const uint32_t * ps, 1026 const uint32_t * pm, 1027 int w) 1028 { 1029 while (w && ((uintptr_t)pd & 15)) 1030 { 1031 uint32_t s = combine1 (ps, pm); 1032 uint32_t d = *pd; 1033 1034 *pd++ = pack_1x128_32 ( 1035 pix_multiply_1x128 ( 1036 unpack_32_1x128 (s), negate_1x128 ( 1037 expand_alpha_1x128 (unpack_32_1x128 (d))))); 1038 w--; 1039 ps++; 1040 if (pm) 1041 pm++; 1042 } 1043 1044 while (w >= 4) 1045 { 1046 __m128i xmm_src_lo, xmm_src_hi; 1047 __m128i xmm_dst_lo, xmm_dst_hi; 1048 1049 xmm_src_hi = combine4 ((__m128i*) ps, (__m128i*)pm); 1050 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 1051 1052 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1053 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1054 1055 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1056 negate_2x128 (xmm_dst_lo, xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1057 1058 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 1059 &xmm_dst_lo, &xmm_dst_hi, 1060 &xmm_dst_lo, &xmm_dst_hi); 1061 1062 save_128_aligned ( 1063 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1064 1065 ps += 4; 1066 pd += 4; 1067 w -= 4; 1068 if (pm) 1069 pm += 4; 1070 } 1071 1072 while (w) 1073 { 1074 uint32_t s = combine1 (ps, pm); 1075 uint32_t d = *pd; 1076 1077 *pd++ = pack_1x128_32 ( 1078 pix_multiply_1x128 ( 1079 unpack_32_1x128 (s), negate_1x128 ( 1080 expand_alpha_1x128 (unpack_32_1x128 (d))))); 1081 w--; 1082 ps++; 1083 if (pm) 1084 pm++; 1085 } 1086 } 1087 1088 static force_inline uint32_t 1089 core_combine_atop_u_pixel_sse2 (uint32_t src, 1090 uint32_t dst) 1091 { 1092 __m128i s = unpack_32_1x128 (src); 1093 __m128i d = unpack_32_1x128 (dst); 1094 1095 __m128i sa = negate_1x128 (expand_alpha_1x128 (s)); 1096 __m128i da = expand_alpha_1x128 (d); 1097 1098 return pack_1x128_32 (pix_add_multiply_1x128 (&s, &da, &d, &sa)); 1099 } 1100 1101 static void 1102 sse2_combine_atop_u (pixman_implementation_t *imp, 1103 pixman_op_t op, 1104 uint32_t * pd, 1105 const uint32_t * ps, 1106 const uint32_t * pm, 1107 int w) 1108 { 1109 uint32_t s, d; 1110 1111 __m128i xmm_src_lo, xmm_src_hi; 1112 __m128i xmm_dst_lo, xmm_dst_hi; 1113 __m128i xmm_alpha_src_lo, xmm_alpha_src_hi; 1114 __m128i xmm_alpha_dst_lo, xmm_alpha_dst_hi; 1115 1116 while (w && ((uintptr_t)pd & 15)) 1117 { 1118 s = combine1 (ps, pm); 1119 d = *pd; 1120 1121 *pd++ = core_combine_atop_u_pixel_sse2 (s, d); 1122 w--; 1123 ps++; 1124 if (pm) 1125 pm++; 1126 } 1127 1128 while (w >= 4) 1129 { 1130 xmm_src_hi = combine4 ((__m128i*)ps, (__m128i*)pm); 1131 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 1132 1133 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1134 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1135 1136 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 1137 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 1138 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 1139 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 1140 1141 negate_2x128 (xmm_alpha_src_lo, xmm_alpha_src_hi, 1142 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 1143 1144 pix_add_multiply_2x128 ( 1145 &xmm_src_lo, &xmm_src_hi, &xmm_alpha_dst_lo, &xmm_alpha_dst_hi, 1146 &xmm_dst_lo, &xmm_dst_hi, &xmm_alpha_src_lo, &xmm_alpha_src_hi, 1147 &xmm_dst_lo, &xmm_dst_hi); 1148 1149 save_128_aligned ( 1150 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1151 1152 ps += 4; 1153 pd += 4; 1154 w -= 4; 1155 if (pm) 1156 pm += 4; 1157 } 1158 1159 while (w) 1160 { 1161 s = combine1 (ps, pm); 1162 d = *pd; 1163 1164 *pd++ = core_combine_atop_u_pixel_sse2 (s, d); 1165 w--; 1166 ps++; 1167 if (pm) 1168 pm++; 1169 } 1170 } 1171 1172 static force_inline uint32_t 1173 core_combine_reverse_atop_u_pixel_sse2 (uint32_t src, 1174 uint32_t dst) 1175 { 1176 __m128i s = unpack_32_1x128 (src); 1177 __m128i d = unpack_32_1x128 (dst); 1178 1179 __m128i sa = expand_alpha_1x128 (s); 1180 __m128i da = negate_1x128 (expand_alpha_1x128 (d)); 1181 1182 return pack_1x128_32 (pix_add_multiply_1x128 (&s, &da, &d, &sa)); 1183 } 1184 1185 static void 1186 sse2_combine_atop_reverse_u (pixman_implementation_t *imp, 1187 pixman_op_t op, 1188 uint32_t * pd, 1189 const uint32_t * ps, 1190 const uint32_t * pm, 1191 int w) 1192 { 1193 uint32_t s, d; 1194 1195 __m128i xmm_src_lo, xmm_src_hi; 1196 __m128i xmm_dst_lo, xmm_dst_hi; 1197 __m128i xmm_alpha_src_lo, xmm_alpha_src_hi; 1198 __m128i xmm_alpha_dst_lo, xmm_alpha_dst_hi; 1199 1200 while (w && ((uintptr_t)pd & 15)) 1201 { 1202 s = combine1 (ps, pm); 1203 d = *pd; 1204 1205 *pd++ = core_combine_reverse_atop_u_pixel_sse2 (s, d); 1206 ps++; 1207 w--; 1208 if (pm) 1209 pm++; 1210 } 1211 1212 while (w >= 4) 1213 { 1214 xmm_src_hi = combine4 ((__m128i*)ps, (__m128i*)pm); 1215 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 1216 1217 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1218 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1219 1220 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 1221 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 1222 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 1223 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 1224 1225 negate_2x128 (xmm_alpha_dst_lo, xmm_alpha_dst_hi, 1226 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 1227 1228 pix_add_multiply_2x128 ( 1229 &xmm_src_lo, &xmm_src_hi, &xmm_alpha_dst_lo, &xmm_alpha_dst_hi, 1230 &xmm_dst_lo, &xmm_dst_hi, &xmm_alpha_src_lo, &xmm_alpha_src_hi, 1231 &xmm_dst_lo, &xmm_dst_hi); 1232 1233 save_128_aligned ( 1234 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1235 1236 ps += 4; 1237 pd += 4; 1238 w -= 4; 1239 if (pm) 1240 pm += 4; 1241 } 1242 1243 while (w) 1244 { 1245 s = combine1 (ps, pm); 1246 d = *pd; 1247 1248 *pd++ = core_combine_reverse_atop_u_pixel_sse2 (s, d); 1249 ps++; 1250 w--; 1251 if (pm) 1252 pm++; 1253 } 1254 } 1255 1256 static force_inline uint32_t 1257 core_combine_xor_u_pixel_sse2 (uint32_t src, 1258 uint32_t dst) 1259 { 1260 __m128i s = unpack_32_1x128 (src); 1261 __m128i d = unpack_32_1x128 (dst); 1262 1263 __m128i neg_d = negate_1x128 (expand_alpha_1x128 (d)); 1264 __m128i neg_s = negate_1x128 (expand_alpha_1x128 (s)); 1265 1266 return pack_1x128_32 (pix_add_multiply_1x128 (&s, &neg_d, &d, &neg_s)); 1267 } 1268 1269 static void 1270 sse2_combine_xor_u (pixman_implementation_t *imp, 1271 pixman_op_t op, 1272 uint32_t * dst, 1273 const uint32_t * src, 1274 const uint32_t * mask, 1275 int width) 1276 { 1277 int w = width; 1278 uint32_t s, d; 1279 uint32_t* pd = dst; 1280 const uint32_t* ps = src; 1281 const uint32_t* pm = mask; 1282 1283 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 1284 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 1285 __m128i xmm_alpha_src_lo, xmm_alpha_src_hi; 1286 __m128i xmm_alpha_dst_lo, xmm_alpha_dst_hi; 1287 1288 while (w && ((uintptr_t)pd & 15)) 1289 { 1290 s = combine1 (ps, pm); 1291 d = *pd; 1292 1293 *pd++ = core_combine_xor_u_pixel_sse2 (s, d); 1294 w--; 1295 ps++; 1296 if (pm) 1297 pm++; 1298 } 1299 1300 while (w >= 4) 1301 { 1302 xmm_src = combine4 ((__m128i*) ps, (__m128i*) pm); 1303 xmm_dst = load_128_aligned ((__m128i*) pd); 1304 1305 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 1306 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 1307 1308 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 1309 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 1310 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 1311 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 1312 1313 negate_2x128 (xmm_alpha_src_lo, xmm_alpha_src_hi, 1314 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 1315 negate_2x128 (xmm_alpha_dst_lo, xmm_alpha_dst_hi, 1316 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 1317 1318 pix_add_multiply_2x128 ( 1319 &xmm_src_lo, &xmm_src_hi, &xmm_alpha_dst_lo, &xmm_alpha_dst_hi, 1320 &xmm_dst_lo, &xmm_dst_hi, &xmm_alpha_src_lo, &xmm_alpha_src_hi, 1321 &xmm_dst_lo, &xmm_dst_hi); 1322 1323 save_128_aligned ( 1324 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1325 1326 ps += 4; 1327 pd += 4; 1328 w -= 4; 1329 if (pm) 1330 pm += 4; 1331 } 1332 1333 while (w) 1334 { 1335 s = combine1 (ps, pm); 1336 d = *pd; 1337 1338 *pd++ = core_combine_xor_u_pixel_sse2 (s, d); 1339 w--; 1340 ps++; 1341 if (pm) 1342 pm++; 1343 } 1344 } 1345 1346 static force_inline void 1347 sse2_combine_add_u (pixman_implementation_t *imp, 1348 pixman_op_t op, 1349 uint32_t * dst, 1350 const uint32_t * src, 1351 const uint32_t * mask, 1352 int width) 1353 { 1354 int w = width; 1355 uint32_t s, d; 1356 uint32_t* pd = dst; 1357 const uint32_t* ps = src; 1358 const uint32_t* pm = mask; 1359 1360 while (w && (uintptr_t)pd & 15) 1361 { 1362 s = combine1 (ps, pm); 1363 d = *pd; 1364 1365 ps++; 1366 if (pm) 1367 pm++; 1368 *pd++ = _mm_cvtsi128_si32 ( 1369 _mm_adds_epu8 (_mm_cvtsi32_si128 (s), _mm_cvtsi32_si128 (d))); 1370 w--; 1371 } 1372 1373 while (w >= 4) 1374 { 1375 __m128i s; 1376 1377 s = combine4 ((__m128i*)ps, (__m128i*)pm); 1378 1379 save_128_aligned ( 1380 (__m128i*)pd, _mm_adds_epu8 (s, load_128_aligned ((__m128i*)pd))); 1381 1382 pd += 4; 1383 ps += 4; 1384 if (pm) 1385 pm += 4; 1386 w -= 4; 1387 } 1388 1389 while (w--) 1390 { 1391 s = combine1 (ps, pm); 1392 d = *pd; 1393 1394 ps++; 1395 *pd++ = _mm_cvtsi128_si32 ( 1396 _mm_adds_epu8 (_mm_cvtsi32_si128 (s), _mm_cvtsi32_si128 (d))); 1397 if (pm) 1398 pm++; 1399 } 1400 } 1401 1402 static force_inline uint32_t 1403 core_combine_saturate_u_pixel_sse2 (uint32_t src, 1404 uint32_t dst) 1405 { 1406 __m128i ms = unpack_32_1x128 (src); 1407 __m128i md = unpack_32_1x128 (dst); 1408 uint32_t sa = src >> 24; 1409 uint32_t da = ~dst >> 24; 1410 1411 if (sa > da) 1412 { 1413 ms = pix_multiply_1x128 ( 1414 ms, expand_alpha_1x128 (unpack_32_1x128 (DIV_UN8 (da, sa) << 24))); 1415 } 1416 1417 return pack_1x128_32 (_mm_adds_epu16 (md, ms)); 1418 } 1419 1420 static void 1421 sse2_combine_saturate_u (pixman_implementation_t *imp, 1422 pixman_op_t op, 1423 uint32_t * pd, 1424 const uint32_t * ps, 1425 const uint32_t * pm, 1426 int w) 1427 { 1428 uint32_t s, d; 1429 1430 uint32_t pack_cmp; 1431 __m128i xmm_src, xmm_dst; 1432 1433 while (w && (uintptr_t)pd & 15) 1434 { 1435 s = combine1 (ps, pm); 1436 d = *pd; 1437 1438 *pd++ = core_combine_saturate_u_pixel_sse2 (s, d); 1439 w--; 1440 ps++; 1441 if (pm) 1442 pm++; 1443 } 1444 1445 while (w >= 4) 1446 { 1447 xmm_dst = load_128_aligned ((__m128i*)pd); 1448 xmm_src = combine4 ((__m128i*)ps, (__m128i*)pm); 1449 1450 pack_cmp = _mm_movemask_epi8 ( 1451 _mm_cmpgt_epi32 ( 1452 _mm_srli_epi32 (xmm_src, 24), 1453 _mm_srli_epi32 (_mm_xor_si128 (xmm_dst, mask_ff000000), 24))); 1454 1455 /* if some alpha src is grater than respective ~alpha dst */ 1456 if (pack_cmp) 1457 { 1458 s = combine1 (ps++, pm); 1459 d = *pd; 1460 *pd++ = core_combine_saturate_u_pixel_sse2 (s, d); 1461 if (pm) 1462 pm++; 1463 1464 s = combine1 (ps++, pm); 1465 d = *pd; 1466 *pd++ = core_combine_saturate_u_pixel_sse2 (s, d); 1467 if (pm) 1468 pm++; 1469 1470 s = combine1 (ps++, pm); 1471 d = *pd; 1472 *pd++ = core_combine_saturate_u_pixel_sse2 (s, d); 1473 if (pm) 1474 pm++; 1475 1476 s = combine1 (ps++, pm); 1477 d = *pd; 1478 *pd++ = core_combine_saturate_u_pixel_sse2 (s, d); 1479 if (pm) 1480 pm++; 1481 } 1482 else 1483 { 1484 save_128_aligned ((__m128i*)pd, _mm_adds_epu8 (xmm_dst, xmm_src)); 1485 1486 pd += 4; 1487 ps += 4; 1488 if (pm) 1489 pm += 4; 1490 } 1491 1492 w -= 4; 1493 } 1494 1495 while (w--) 1496 { 1497 s = combine1 (ps, pm); 1498 d = *pd; 1499 1500 *pd++ = core_combine_saturate_u_pixel_sse2 (s, d); 1501 ps++; 1502 if (pm) 1503 pm++; 1504 } 1505 } 1506 1507 static void 1508 sse2_combine_src_ca (pixman_implementation_t *imp, 1509 pixman_op_t op, 1510 uint32_t * pd, 1511 const uint32_t * ps, 1512 const uint32_t * pm, 1513 int w) 1514 { 1515 uint32_t s, m; 1516 1517 __m128i xmm_src_lo, xmm_src_hi; 1518 __m128i xmm_mask_lo, xmm_mask_hi; 1519 __m128i xmm_dst_lo, xmm_dst_hi; 1520 1521 while (w && (uintptr_t)pd & 15) 1522 { 1523 s = *ps++; 1524 m = *pm++; 1525 *pd++ = pack_1x128_32 ( 1526 pix_multiply_1x128 (unpack_32_1x128 (s), unpack_32_1x128 (m))); 1527 w--; 1528 } 1529 1530 while (w >= 4) 1531 { 1532 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1533 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1534 1535 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1536 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1537 1538 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 1539 &xmm_mask_lo, &xmm_mask_hi, 1540 &xmm_dst_lo, &xmm_dst_hi); 1541 1542 save_128_aligned ( 1543 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1544 1545 ps += 4; 1546 pd += 4; 1547 pm += 4; 1548 w -= 4; 1549 } 1550 1551 while (w) 1552 { 1553 s = *ps++; 1554 m = *pm++; 1555 *pd++ = pack_1x128_32 ( 1556 pix_multiply_1x128 (unpack_32_1x128 (s), unpack_32_1x128 (m))); 1557 w--; 1558 } 1559 } 1560 1561 static force_inline uint32_t 1562 core_combine_over_ca_pixel_sse2 (uint32_t src, 1563 uint32_t mask, 1564 uint32_t dst) 1565 { 1566 __m128i s = unpack_32_1x128 (src); 1567 __m128i expAlpha = expand_alpha_1x128 (s); 1568 __m128i unpk_mask = unpack_32_1x128 (mask); 1569 __m128i unpk_dst = unpack_32_1x128 (dst); 1570 1571 return pack_1x128_32 (in_over_1x128 (&s, &expAlpha, &unpk_mask, &unpk_dst)); 1572 } 1573 1574 static void 1575 sse2_combine_over_ca (pixman_implementation_t *imp, 1576 pixman_op_t op, 1577 uint32_t * pd, 1578 const uint32_t * ps, 1579 const uint32_t * pm, 1580 int w) 1581 { 1582 uint32_t s, m, d; 1583 1584 __m128i xmm_alpha_lo, xmm_alpha_hi; 1585 __m128i xmm_src_lo, xmm_src_hi; 1586 __m128i xmm_dst_lo, xmm_dst_hi; 1587 __m128i xmm_mask_lo, xmm_mask_hi; 1588 1589 while (w && (uintptr_t)pd & 15) 1590 { 1591 s = *ps++; 1592 m = *pm++; 1593 d = *pd; 1594 1595 *pd++ = core_combine_over_ca_pixel_sse2 (s, m, d); 1596 w--; 1597 } 1598 1599 while (w >= 4) 1600 { 1601 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 1602 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1603 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1604 1605 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1606 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1607 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1608 1609 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 1610 &xmm_alpha_lo, &xmm_alpha_hi); 1611 1612 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, 1613 &xmm_alpha_lo, &xmm_alpha_hi, 1614 &xmm_mask_lo, &xmm_mask_hi, 1615 &xmm_dst_lo, &xmm_dst_hi); 1616 1617 save_128_aligned ( 1618 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1619 1620 ps += 4; 1621 pd += 4; 1622 pm += 4; 1623 w -= 4; 1624 } 1625 1626 while (w) 1627 { 1628 s = *ps++; 1629 m = *pm++; 1630 d = *pd; 1631 1632 *pd++ = core_combine_over_ca_pixel_sse2 (s, m, d); 1633 w--; 1634 } 1635 } 1636 1637 static force_inline uint32_t 1638 core_combine_over_reverse_ca_pixel_sse2 (uint32_t src, 1639 uint32_t mask, 1640 uint32_t dst) 1641 { 1642 __m128i d = unpack_32_1x128 (dst); 1643 1644 return pack_1x128_32 ( 1645 over_1x128 (d, expand_alpha_1x128 (d), 1646 pix_multiply_1x128 (unpack_32_1x128 (src), 1647 unpack_32_1x128 (mask)))); 1648 } 1649 1650 static void 1651 sse2_combine_over_reverse_ca (pixman_implementation_t *imp, 1652 pixman_op_t op, 1653 uint32_t * pd, 1654 const uint32_t * ps, 1655 const uint32_t * pm, 1656 int w) 1657 { 1658 uint32_t s, m, d; 1659 1660 __m128i xmm_alpha_lo, xmm_alpha_hi; 1661 __m128i xmm_src_lo, xmm_src_hi; 1662 __m128i xmm_dst_lo, xmm_dst_hi; 1663 __m128i xmm_mask_lo, xmm_mask_hi; 1664 1665 while (w && (uintptr_t)pd & 15) 1666 { 1667 s = *ps++; 1668 m = *pm++; 1669 d = *pd; 1670 1671 *pd++ = core_combine_over_reverse_ca_pixel_sse2 (s, m, d); 1672 w--; 1673 } 1674 1675 while (w >= 4) 1676 { 1677 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 1678 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1679 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1680 1681 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1682 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1683 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1684 1685 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 1686 &xmm_alpha_lo, &xmm_alpha_hi); 1687 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 1688 &xmm_mask_lo, &xmm_mask_hi, 1689 &xmm_mask_lo, &xmm_mask_hi); 1690 1691 over_2x128 (&xmm_dst_lo, &xmm_dst_hi, 1692 &xmm_alpha_lo, &xmm_alpha_hi, 1693 &xmm_mask_lo, &xmm_mask_hi); 1694 1695 save_128_aligned ( 1696 (__m128i*)pd, pack_2x128_128 (xmm_mask_lo, xmm_mask_hi)); 1697 1698 ps += 4; 1699 pd += 4; 1700 pm += 4; 1701 w -= 4; 1702 } 1703 1704 while (w) 1705 { 1706 s = *ps++; 1707 m = *pm++; 1708 d = *pd; 1709 1710 *pd++ = core_combine_over_reverse_ca_pixel_sse2 (s, m, d); 1711 w--; 1712 } 1713 } 1714 1715 static void 1716 sse2_combine_in_ca (pixman_implementation_t *imp, 1717 pixman_op_t op, 1718 uint32_t * pd, 1719 const uint32_t * ps, 1720 const uint32_t * pm, 1721 int w) 1722 { 1723 uint32_t s, m, d; 1724 1725 __m128i xmm_alpha_lo, xmm_alpha_hi; 1726 __m128i xmm_src_lo, xmm_src_hi; 1727 __m128i xmm_dst_lo, xmm_dst_hi; 1728 __m128i xmm_mask_lo, xmm_mask_hi; 1729 1730 while (w && (uintptr_t)pd & 15) 1731 { 1732 s = *ps++; 1733 m = *pm++; 1734 d = *pd; 1735 1736 *pd++ = pack_1x128_32 ( 1737 pix_multiply_1x128 ( 1738 pix_multiply_1x128 (unpack_32_1x128 (s), unpack_32_1x128 (m)), 1739 expand_alpha_1x128 (unpack_32_1x128 (d)))); 1740 1741 w--; 1742 } 1743 1744 while (w >= 4) 1745 { 1746 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 1747 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1748 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1749 1750 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1751 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1752 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1753 1754 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 1755 &xmm_alpha_lo, &xmm_alpha_hi); 1756 1757 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 1758 &xmm_mask_lo, &xmm_mask_hi, 1759 &xmm_dst_lo, &xmm_dst_hi); 1760 1761 pix_multiply_2x128 (&xmm_dst_lo, &xmm_dst_hi, 1762 &xmm_alpha_lo, &xmm_alpha_hi, 1763 &xmm_dst_lo, &xmm_dst_hi); 1764 1765 save_128_aligned ( 1766 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1767 1768 ps += 4; 1769 pd += 4; 1770 pm += 4; 1771 w -= 4; 1772 } 1773 1774 while (w) 1775 { 1776 s = *ps++; 1777 m = *pm++; 1778 d = *pd; 1779 1780 *pd++ = pack_1x128_32 ( 1781 pix_multiply_1x128 ( 1782 pix_multiply_1x128 ( 1783 unpack_32_1x128 (s), unpack_32_1x128 (m)), 1784 expand_alpha_1x128 (unpack_32_1x128 (d)))); 1785 1786 w--; 1787 } 1788 } 1789 1790 static void 1791 sse2_combine_in_reverse_ca (pixman_implementation_t *imp, 1792 pixman_op_t op, 1793 uint32_t * pd, 1794 const uint32_t * ps, 1795 const uint32_t * pm, 1796 int w) 1797 { 1798 uint32_t s, m, d; 1799 1800 __m128i xmm_alpha_lo, xmm_alpha_hi; 1801 __m128i xmm_src_lo, xmm_src_hi; 1802 __m128i xmm_dst_lo, xmm_dst_hi; 1803 __m128i xmm_mask_lo, xmm_mask_hi; 1804 1805 while (w && (uintptr_t)pd & 15) 1806 { 1807 s = *ps++; 1808 m = *pm++; 1809 d = *pd; 1810 1811 *pd++ = pack_1x128_32 ( 1812 pix_multiply_1x128 ( 1813 unpack_32_1x128 (d), 1814 pix_multiply_1x128 (unpack_32_1x128 (m), 1815 expand_alpha_1x128 (unpack_32_1x128 (s))))); 1816 w--; 1817 } 1818 1819 while (w >= 4) 1820 { 1821 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 1822 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1823 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1824 1825 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1826 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1827 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1828 1829 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 1830 &xmm_alpha_lo, &xmm_alpha_hi); 1831 pix_multiply_2x128 (&xmm_mask_lo, &xmm_mask_hi, 1832 &xmm_alpha_lo, &xmm_alpha_hi, 1833 &xmm_alpha_lo, &xmm_alpha_hi); 1834 1835 pix_multiply_2x128 (&xmm_dst_lo, &xmm_dst_hi, 1836 &xmm_alpha_lo, &xmm_alpha_hi, 1837 &xmm_dst_lo, &xmm_dst_hi); 1838 1839 save_128_aligned ( 1840 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1841 1842 ps += 4; 1843 pd += 4; 1844 pm += 4; 1845 w -= 4; 1846 } 1847 1848 while (w) 1849 { 1850 s = *ps++; 1851 m = *pm++; 1852 d = *pd; 1853 1854 *pd++ = pack_1x128_32 ( 1855 pix_multiply_1x128 ( 1856 unpack_32_1x128 (d), 1857 pix_multiply_1x128 (unpack_32_1x128 (m), 1858 expand_alpha_1x128 (unpack_32_1x128 (s))))); 1859 w--; 1860 } 1861 } 1862 1863 static void 1864 sse2_combine_out_ca (pixman_implementation_t *imp, 1865 pixman_op_t op, 1866 uint32_t * pd, 1867 const uint32_t * ps, 1868 const uint32_t * pm, 1869 int w) 1870 { 1871 uint32_t s, m, d; 1872 1873 __m128i xmm_alpha_lo, xmm_alpha_hi; 1874 __m128i xmm_src_lo, xmm_src_hi; 1875 __m128i xmm_dst_lo, xmm_dst_hi; 1876 __m128i xmm_mask_lo, xmm_mask_hi; 1877 1878 while (w && (uintptr_t)pd & 15) 1879 { 1880 s = *ps++; 1881 m = *pm++; 1882 d = *pd; 1883 1884 *pd++ = pack_1x128_32 ( 1885 pix_multiply_1x128 ( 1886 pix_multiply_1x128 ( 1887 unpack_32_1x128 (s), unpack_32_1x128 (m)), 1888 negate_1x128 (expand_alpha_1x128 (unpack_32_1x128 (d))))); 1889 w--; 1890 } 1891 1892 while (w >= 4) 1893 { 1894 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 1895 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1896 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1897 1898 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1899 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1900 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1901 1902 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 1903 &xmm_alpha_lo, &xmm_alpha_hi); 1904 negate_2x128 (xmm_alpha_lo, xmm_alpha_hi, 1905 &xmm_alpha_lo, &xmm_alpha_hi); 1906 1907 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 1908 &xmm_mask_lo, &xmm_mask_hi, 1909 &xmm_dst_lo, &xmm_dst_hi); 1910 pix_multiply_2x128 (&xmm_dst_lo, &xmm_dst_hi, 1911 &xmm_alpha_lo, &xmm_alpha_hi, 1912 &xmm_dst_lo, &xmm_dst_hi); 1913 1914 save_128_aligned ( 1915 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1916 1917 ps += 4; 1918 pd += 4; 1919 pm += 4; 1920 w -= 4; 1921 } 1922 1923 while (w) 1924 { 1925 s = *ps++; 1926 m = *pm++; 1927 d = *pd; 1928 1929 *pd++ = pack_1x128_32 ( 1930 pix_multiply_1x128 ( 1931 pix_multiply_1x128 ( 1932 unpack_32_1x128 (s), unpack_32_1x128 (m)), 1933 negate_1x128 (expand_alpha_1x128 (unpack_32_1x128 (d))))); 1934 1935 w--; 1936 } 1937 } 1938 1939 static void 1940 sse2_combine_out_reverse_ca (pixman_implementation_t *imp, 1941 pixman_op_t op, 1942 uint32_t * pd, 1943 const uint32_t * ps, 1944 const uint32_t * pm, 1945 int w) 1946 { 1947 uint32_t s, m, d; 1948 1949 __m128i xmm_alpha_lo, xmm_alpha_hi; 1950 __m128i xmm_src_lo, xmm_src_hi; 1951 __m128i xmm_dst_lo, xmm_dst_hi; 1952 __m128i xmm_mask_lo, xmm_mask_hi; 1953 1954 while (w && (uintptr_t)pd & 15) 1955 { 1956 s = *ps++; 1957 m = *pm++; 1958 d = *pd; 1959 1960 *pd++ = pack_1x128_32 ( 1961 pix_multiply_1x128 ( 1962 unpack_32_1x128 (d), 1963 negate_1x128 (pix_multiply_1x128 ( 1964 unpack_32_1x128 (m), 1965 expand_alpha_1x128 (unpack_32_1x128 (s)))))); 1966 w--; 1967 } 1968 1969 while (w >= 4) 1970 { 1971 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 1972 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 1973 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 1974 1975 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 1976 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 1977 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 1978 1979 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 1980 &xmm_alpha_lo, &xmm_alpha_hi); 1981 1982 pix_multiply_2x128 (&xmm_mask_lo, &xmm_mask_hi, 1983 &xmm_alpha_lo, &xmm_alpha_hi, 1984 &xmm_mask_lo, &xmm_mask_hi); 1985 1986 negate_2x128 (xmm_mask_lo, xmm_mask_hi, 1987 &xmm_mask_lo, &xmm_mask_hi); 1988 1989 pix_multiply_2x128 (&xmm_dst_lo, &xmm_dst_hi, 1990 &xmm_mask_lo, &xmm_mask_hi, 1991 &xmm_dst_lo, &xmm_dst_hi); 1992 1993 save_128_aligned ( 1994 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 1995 1996 ps += 4; 1997 pd += 4; 1998 pm += 4; 1999 w -= 4; 2000 } 2001 2002 while (w) 2003 { 2004 s = *ps++; 2005 m = *pm++; 2006 d = *pd; 2007 2008 *pd++ = pack_1x128_32 ( 2009 pix_multiply_1x128 ( 2010 unpack_32_1x128 (d), 2011 negate_1x128 (pix_multiply_1x128 ( 2012 unpack_32_1x128 (m), 2013 expand_alpha_1x128 (unpack_32_1x128 (s)))))); 2014 w--; 2015 } 2016 } 2017 2018 static force_inline uint32_t 2019 core_combine_atop_ca_pixel_sse2 (uint32_t src, 2020 uint32_t mask, 2021 uint32_t dst) 2022 { 2023 __m128i m = unpack_32_1x128 (mask); 2024 __m128i s = unpack_32_1x128 (src); 2025 __m128i d = unpack_32_1x128 (dst); 2026 __m128i sa = expand_alpha_1x128 (s); 2027 __m128i da = expand_alpha_1x128 (d); 2028 2029 s = pix_multiply_1x128 (s, m); 2030 m = negate_1x128 (pix_multiply_1x128 (m, sa)); 2031 2032 return pack_1x128_32 (pix_add_multiply_1x128 (&d, &m, &s, &da)); 2033 } 2034 2035 static void 2036 sse2_combine_atop_ca (pixman_implementation_t *imp, 2037 pixman_op_t op, 2038 uint32_t * pd, 2039 const uint32_t * ps, 2040 const uint32_t * pm, 2041 int w) 2042 { 2043 uint32_t s, m, d; 2044 2045 __m128i xmm_src_lo, xmm_src_hi; 2046 __m128i xmm_dst_lo, xmm_dst_hi; 2047 __m128i xmm_alpha_src_lo, xmm_alpha_src_hi; 2048 __m128i xmm_alpha_dst_lo, xmm_alpha_dst_hi; 2049 __m128i xmm_mask_lo, xmm_mask_hi; 2050 2051 while (w && (uintptr_t)pd & 15) 2052 { 2053 s = *ps++; 2054 m = *pm++; 2055 d = *pd; 2056 2057 *pd++ = core_combine_atop_ca_pixel_sse2 (s, m, d); 2058 w--; 2059 } 2060 2061 while (w >= 4) 2062 { 2063 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 2064 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 2065 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 2066 2067 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 2068 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 2069 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 2070 2071 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 2072 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 2073 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 2074 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 2075 2076 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 2077 &xmm_mask_lo, &xmm_mask_hi, 2078 &xmm_src_lo, &xmm_src_hi); 2079 pix_multiply_2x128 (&xmm_mask_lo, &xmm_mask_hi, 2080 &xmm_alpha_src_lo, &xmm_alpha_src_hi, 2081 &xmm_mask_lo, &xmm_mask_hi); 2082 2083 negate_2x128 (xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 2084 2085 pix_add_multiply_2x128 ( 2086 &xmm_dst_lo, &xmm_dst_hi, &xmm_mask_lo, &xmm_mask_hi, 2087 &xmm_src_lo, &xmm_src_hi, &xmm_alpha_dst_lo, &xmm_alpha_dst_hi, 2088 &xmm_dst_lo, &xmm_dst_hi); 2089 2090 save_128_aligned ( 2091 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 2092 2093 ps += 4; 2094 pd += 4; 2095 pm += 4; 2096 w -= 4; 2097 } 2098 2099 while (w) 2100 { 2101 s = *ps++; 2102 m = *pm++; 2103 d = *pd; 2104 2105 *pd++ = core_combine_atop_ca_pixel_sse2 (s, m, d); 2106 w--; 2107 } 2108 } 2109 2110 static force_inline uint32_t 2111 core_combine_reverse_atop_ca_pixel_sse2 (uint32_t src, 2112 uint32_t mask, 2113 uint32_t dst) 2114 { 2115 __m128i m = unpack_32_1x128 (mask); 2116 __m128i s = unpack_32_1x128 (src); 2117 __m128i d = unpack_32_1x128 (dst); 2118 2119 __m128i da = negate_1x128 (expand_alpha_1x128 (d)); 2120 __m128i sa = expand_alpha_1x128 (s); 2121 2122 s = pix_multiply_1x128 (s, m); 2123 m = pix_multiply_1x128 (m, sa); 2124 2125 return pack_1x128_32 (pix_add_multiply_1x128 (&d, &m, &s, &da)); 2126 } 2127 2128 static void 2129 sse2_combine_atop_reverse_ca (pixman_implementation_t *imp, 2130 pixman_op_t op, 2131 uint32_t * pd, 2132 const uint32_t * ps, 2133 const uint32_t * pm, 2134 int w) 2135 { 2136 uint32_t s, m, d; 2137 2138 __m128i xmm_src_lo, xmm_src_hi; 2139 __m128i xmm_dst_lo, xmm_dst_hi; 2140 __m128i xmm_alpha_src_lo, xmm_alpha_src_hi; 2141 __m128i xmm_alpha_dst_lo, xmm_alpha_dst_hi; 2142 __m128i xmm_mask_lo, xmm_mask_hi; 2143 2144 while (w && (uintptr_t)pd & 15) 2145 { 2146 s = *ps++; 2147 m = *pm++; 2148 d = *pd; 2149 2150 *pd++ = core_combine_reverse_atop_ca_pixel_sse2 (s, m, d); 2151 w--; 2152 } 2153 2154 while (w >= 4) 2155 { 2156 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 2157 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 2158 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 2159 2160 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 2161 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 2162 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 2163 2164 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 2165 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 2166 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 2167 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 2168 2169 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 2170 &xmm_mask_lo, &xmm_mask_hi, 2171 &xmm_src_lo, &xmm_src_hi); 2172 pix_multiply_2x128 (&xmm_mask_lo, &xmm_mask_hi, 2173 &xmm_alpha_src_lo, &xmm_alpha_src_hi, 2174 &xmm_mask_lo, &xmm_mask_hi); 2175 2176 negate_2x128 (xmm_alpha_dst_lo, xmm_alpha_dst_hi, 2177 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 2178 2179 pix_add_multiply_2x128 ( 2180 &xmm_dst_lo, &xmm_dst_hi, &xmm_mask_lo, &xmm_mask_hi, 2181 &xmm_src_lo, &xmm_src_hi, &xmm_alpha_dst_lo, &xmm_alpha_dst_hi, 2182 &xmm_dst_lo, &xmm_dst_hi); 2183 2184 save_128_aligned ( 2185 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 2186 2187 ps += 4; 2188 pd += 4; 2189 pm += 4; 2190 w -= 4; 2191 } 2192 2193 while (w) 2194 { 2195 s = *ps++; 2196 m = *pm++; 2197 d = *pd; 2198 2199 *pd++ = core_combine_reverse_atop_ca_pixel_sse2 (s, m, d); 2200 w--; 2201 } 2202 } 2203 2204 static force_inline uint32_t 2205 core_combine_xor_ca_pixel_sse2 (uint32_t src, 2206 uint32_t mask, 2207 uint32_t dst) 2208 { 2209 __m128i a = unpack_32_1x128 (mask); 2210 __m128i s = unpack_32_1x128 (src); 2211 __m128i d = unpack_32_1x128 (dst); 2212 2213 __m128i alpha_dst = negate_1x128 (pix_multiply_1x128 ( 2214 a, expand_alpha_1x128 (s))); 2215 __m128i dest = pix_multiply_1x128 (s, a); 2216 __m128i alpha_src = negate_1x128 (expand_alpha_1x128 (d)); 2217 2218 return pack_1x128_32 (pix_add_multiply_1x128 (&d, 2219 &alpha_dst, 2220 &dest, 2221 &alpha_src)); 2222 } 2223 2224 static void 2225 sse2_combine_xor_ca (pixman_implementation_t *imp, 2226 pixman_op_t op, 2227 uint32_t * pd, 2228 const uint32_t * ps, 2229 const uint32_t * pm, 2230 int w) 2231 { 2232 uint32_t s, m, d; 2233 2234 __m128i xmm_src_lo, xmm_src_hi; 2235 __m128i xmm_dst_lo, xmm_dst_hi; 2236 __m128i xmm_alpha_src_lo, xmm_alpha_src_hi; 2237 __m128i xmm_alpha_dst_lo, xmm_alpha_dst_hi; 2238 __m128i xmm_mask_lo, xmm_mask_hi; 2239 2240 while (w && (uintptr_t)pd & 15) 2241 { 2242 s = *ps++; 2243 m = *pm++; 2244 d = *pd; 2245 2246 *pd++ = core_combine_xor_ca_pixel_sse2 (s, m, d); 2247 w--; 2248 } 2249 2250 while (w >= 4) 2251 { 2252 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 2253 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 2254 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 2255 2256 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 2257 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 2258 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 2259 2260 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 2261 &xmm_alpha_src_lo, &xmm_alpha_src_hi); 2262 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, 2263 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 2264 2265 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 2266 &xmm_mask_lo, &xmm_mask_hi, 2267 &xmm_src_lo, &xmm_src_hi); 2268 pix_multiply_2x128 (&xmm_mask_lo, &xmm_mask_hi, 2269 &xmm_alpha_src_lo, &xmm_alpha_src_hi, 2270 &xmm_mask_lo, &xmm_mask_hi); 2271 2272 negate_2x128 (xmm_alpha_dst_lo, xmm_alpha_dst_hi, 2273 &xmm_alpha_dst_lo, &xmm_alpha_dst_hi); 2274 negate_2x128 (xmm_mask_lo, xmm_mask_hi, 2275 &xmm_mask_lo, &xmm_mask_hi); 2276 2277 pix_add_multiply_2x128 ( 2278 &xmm_dst_lo, &xmm_dst_hi, &xmm_mask_lo, &xmm_mask_hi, 2279 &xmm_src_lo, &xmm_src_hi, &xmm_alpha_dst_lo, &xmm_alpha_dst_hi, 2280 &xmm_dst_lo, &xmm_dst_hi); 2281 2282 save_128_aligned ( 2283 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 2284 2285 ps += 4; 2286 pd += 4; 2287 pm += 4; 2288 w -= 4; 2289 } 2290 2291 while (w) 2292 { 2293 s = *ps++; 2294 m = *pm++; 2295 d = *pd; 2296 2297 *pd++ = core_combine_xor_ca_pixel_sse2 (s, m, d); 2298 w--; 2299 } 2300 } 2301 2302 static void 2303 sse2_combine_add_ca (pixman_implementation_t *imp, 2304 pixman_op_t op, 2305 uint32_t * pd, 2306 const uint32_t * ps, 2307 const uint32_t * pm, 2308 int w) 2309 { 2310 uint32_t s, m, d; 2311 2312 __m128i xmm_src_lo, xmm_src_hi; 2313 __m128i xmm_dst_lo, xmm_dst_hi; 2314 __m128i xmm_mask_lo, xmm_mask_hi; 2315 2316 while (w && (uintptr_t)pd & 15) 2317 { 2318 s = *ps++; 2319 m = *pm++; 2320 d = *pd; 2321 2322 *pd++ = pack_1x128_32 ( 2323 _mm_adds_epu8 (pix_multiply_1x128 (unpack_32_1x128 (s), 2324 unpack_32_1x128 (m)), 2325 unpack_32_1x128 (d))); 2326 w--; 2327 } 2328 2329 while (w >= 4) 2330 { 2331 xmm_src_hi = load_128_unaligned ((__m128i*)ps); 2332 xmm_mask_hi = load_128_unaligned ((__m128i*)pm); 2333 xmm_dst_hi = load_128_aligned ((__m128i*)pd); 2334 2335 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 2336 unpack_128_2x128 (xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 2337 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 2338 2339 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 2340 &xmm_mask_lo, &xmm_mask_hi, 2341 &xmm_src_lo, &xmm_src_hi); 2342 2343 save_128_aligned ( 2344 (__m128i*)pd, pack_2x128_128 ( 2345 _mm_adds_epu8 (xmm_src_lo, xmm_dst_lo), 2346 _mm_adds_epu8 (xmm_src_hi, xmm_dst_hi))); 2347 2348 ps += 4; 2349 pd += 4; 2350 pm += 4; 2351 w -= 4; 2352 } 2353 2354 while (w) 2355 { 2356 s = *ps++; 2357 m = *pm++; 2358 d = *pd; 2359 2360 *pd++ = pack_1x128_32 ( 2361 _mm_adds_epu8 (pix_multiply_1x128 (unpack_32_1x128 (s), 2362 unpack_32_1x128 (m)), 2363 unpack_32_1x128 (d))); 2364 w--; 2365 } 2366 } 2367 2368 static force_inline __m128i 2369 create_mask_16_128 (uint16_t mask) 2370 { 2371 return _mm_set1_epi16 (mask); 2372 } 2373 2374 /* Work around a code generation bug in Sun Studio 12. */ 2375 #if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) 2376 # define create_mask_2x32_128(mask0, mask1) \ 2377 (_mm_set_epi32 ((mask0), (mask1), (mask0), (mask1))) 2378 #else 2379 static force_inline __m128i 2380 create_mask_2x32_128 (uint32_t mask0, 2381 uint32_t mask1) 2382 { 2383 return _mm_set_epi32 (mask0, mask1, mask0, mask1); 2384 } 2385 #endif 2386 2387 static void 2388 sse2_composite_over_n_8888 (pixman_implementation_t *imp, 2389 pixman_composite_info_t *info) 2390 { 2391 PIXMAN_COMPOSITE_ARGS (info); 2392 uint32_t src; 2393 uint32_t *dst_line, *dst, d; 2394 int32_t w; 2395 int dst_stride; 2396 __m128i xmm_src, xmm_alpha; 2397 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 2398 2399 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 2400 2401 if (src == 0) 2402 return; 2403 2404 PIXMAN_IMAGE_GET_LINE ( 2405 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 2406 2407 xmm_src = expand_pixel_32_1x128 (src); 2408 xmm_alpha = expand_alpha_1x128 (xmm_src); 2409 2410 while (height--) 2411 { 2412 dst = dst_line; 2413 2414 dst_line += dst_stride; 2415 w = width; 2416 2417 while (w && (uintptr_t)dst & 15) 2418 { 2419 d = *dst; 2420 *dst++ = pack_1x128_32 (over_1x128 (xmm_src, 2421 xmm_alpha, 2422 unpack_32_1x128 (d))); 2423 w--; 2424 } 2425 2426 while (w >= 4) 2427 { 2428 xmm_dst = load_128_aligned ((__m128i*)dst); 2429 2430 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 2431 2432 over_2x128 (&xmm_src, &xmm_src, 2433 &xmm_alpha, &xmm_alpha, 2434 &xmm_dst_lo, &xmm_dst_hi); 2435 2436 /* rebuid the 4 pixel data and save*/ 2437 save_128_aligned ( 2438 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 2439 2440 w -= 4; 2441 dst += 4; 2442 } 2443 2444 while (w) 2445 { 2446 d = *dst; 2447 *dst++ = pack_1x128_32 (over_1x128 (xmm_src, 2448 xmm_alpha, 2449 unpack_32_1x128 (d))); 2450 w--; 2451 } 2452 2453 } 2454 } 2455 2456 static void 2457 sse2_composite_over_n_0565 (pixman_implementation_t *imp, 2458 pixman_composite_info_t *info) 2459 { 2460 PIXMAN_COMPOSITE_ARGS (info); 2461 uint32_t src; 2462 uint16_t *dst_line, *dst, d; 2463 int32_t w; 2464 int dst_stride; 2465 __m128i xmm_src, xmm_alpha; 2466 __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3; 2467 2468 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 2469 2470 if (src == 0) 2471 return; 2472 2473 PIXMAN_IMAGE_GET_LINE ( 2474 dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); 2475 2476 xmm_src = expand_pixel_32_1x128 (src); 2477 xmm_alpha = expand_alpha_1x128 (xmm_src); 2478 2479 while (height--) 2480 { 2481 dst = dst_line; 2482 2483 dst_line += dst_stride; 2484 w = width; 2485 2486 while (w && (uintptr_t)dst & 15) 2487 { 2488 d = *dst; 2489 2490 *dst++ = pack_565_32_16 ( 2491 pack_1x128_32 (over_1x128 (xmm_src, 2492 xmm_alpha, 2493 expand565_16_1x128 (d)))); 2494 w--; 2495 } 2496 2497 while (w >= 8) 2498 { 2499 xmm_dst = load_128_aligned ((__m128i*)dst); 2500 2501 unpack_565_128_4x128 (xmm_dst, 2502 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3); 2503 2504 over_2x128 (&xmm_src, &xmm_src, 2505 &xmm_alpha, &xmm_alpha, 2506 &xmm_dst0, &xmm_dst1); 2507 over_2x128 (&xmm_src, &xmm_src, 2508 &xmm_alpha, &xmm_alpha, 2509 &xmm_dst2, &xmm_dst3); 2510 2511 xmm_dst = pack_565_4x128_128 ( 2512 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3); 2513 2514 save_128_aligned ((__m128i*)dst, xmm_dst); 2515 2516 dst += 8; 2517 w -= 8; 2518 } 2519 2520 while (w--) 2521 { 2522 d = *dst; 2523 *dst++ = pack_565_32_16 ( 2524 pack_1x128_32 (over_1x128 (xmm_src, xmm_alpha, 2525 expand565_16_1x128 (d)))); 2526 } 2527 } 2528 2529 } 2530 2531 static void 2532 sse2_composite_add_n_8888_8888_ca (pixman_implementation_t *imp, 2533 pixman_composite_info_t *info) 2534 { 2535 PIXMAN_COMPOSITE_ARGS (info); 2536 uint32_t src; 2537 uint32_t *dst_line, d; 2538 uint32_t *mask_line, m; 2539 uint32_t pack_cmp; 2540 int dst_stride, mask_stride; 2541 2542 __m128i xmm_src; 2543 __m128i xmm_dst; 2544 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 2545 2546 __m128i mmx_src, mmx_mask, mmx_dest; 2547 2548 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 2549 2550 if (src == 0) 2551 return; 2552 2553 PIXMAN_IMAGE_GET_LINE ( 2554 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 2555 PIXMAN_IMAGE_GET_LINE ( 2556 mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1); 2557 2558 xmm_src = _mm_unpacklo_epi8 ( 2559 create_mask_2x32_128 (src, src), _mm_setzero_si128 ()); 2560 mmx_src = xmm_src; 2561 2562 while (height--) 2563 { 2564 int w = width; 2565 const uint32_t *pm = (uint32_t *)mask_line; 2566 uint32_t *pd = (uint32_t *)dst_line; 2567 2568 dst_line += dst_stride; 2569 mask_line += mask_stride; 2570 2571 while (w && (uintptr_t)pd & 15) 2572 { 2573 m = *pm++; 2574 2575 if (m) 2576 { 2577 d = *pd; 2578 2579 mmx_mask = unpack_32_1x128 (m); 2580 mmx_dest = unpack_32_1x128 (d); 2581 2582 *pd = pack_1x128_32 ( 2583 _mm_adds_epu8 (pix_multiply_1x128 (mmx_mask, mmx_src), 2584 mmx_dest)); 2585 } 2586 2587 pd++; 2588 w--; 2589 } 2590 2591 while (w >= 4) 2592 { 2593 xmm_mask = load_128_unaligned ((__m128i*)pm); 2594 2595 pack_cmp = 2596 _mm_movemask_epi8 ( 2597 _mm_cmpeq_epi32 (xmm_mask, _mm_setzero_si128 ())); 2598 2599 /* if all bits in mask are zero, pack_cmp are equal to 0xffff */ 2600 if (pack_cmp != 0xffff) 2601 { 2602 xmm_dst = load_128_aligned ((__m128i*)pd); 2603 2604 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 2605 2606 pix_multiply_2x128 (&xmm_src, &xmm_src, 2607 &xmm_mask_lo, &xmm_mask_hi, 2608 &xmm_mask_lo, &xmm_mask_hi); 2609 xmm_mask_hi = pack_2x128_128 (xmm_mask_lo, xmm_mask_hi); 2610 2611 save_128_aligned ( 2612 (__m128i*)pd, _mm_adds_epu8 (xmm_mask_hi, xmm_dst)); 2613 } 2614 2615 pd += 4; 2616 pm += 4; 2617 w -= 4; 2618 } 2619 2620 while (w) 2621 { 2622 m = *pm++; 2623 2624 if (m) 2625 { 2626 d = *pd; 2627 2628 mmx_mask = unpack_32_1x128 (m); 2629 mmx_dest = unpack_32_1x128 (d); 2630 2631 *pd = pack_1x128_32 ( 2632 _mm_adds_epu8 (pix_multiply_1x128 (mmx_mask, mmx_src), 2633 mmx_dest)); 2634 } 2635 2636 pd++; 2637 w--; 2638 } 2639 } 2640 2641 } 2642 2643 static void 2644 sse2_composite_over_n_8888_8888_ca (pixman_implementation_t *imp, 2645 pixman_composite_info_t *info) 2646 { 2647 PIXMAN_COMPOSITE_ARGS (info); 2648 uint32_t src; 2649 uint32_t *dst_line, d; 2650 uint32_t *mask_line, m; 2651 uint32_t pack_cmp; 2652 int dst_stride, mask_stride; 2653 2654 __m128i xmm_src, xmm_alpha; 2655 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 2656 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 2657 2658 __m128i mmx_src, mmx_alpha, mmx_mask, mmx_dest; 2659 2660 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 2661 2662 if (src == 0) 2663 return; 2664 2665 PIXMAN_IMAGE_GET_LINE ( 2666 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 2667 PIXMAN_IMAGE_GET_LINE ( 2668 mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1); 2669 2670 xmm_src = _mm_unpacklo_epi8 ( 2671 create_mask_2x32_128 (src, src), _mm_setzero_si128 ()); 2672 xmm_alpha = expand_alpha_1x128 (xmm_src); 2673 mmx_src = xmm_src; 2674 mmx_alpha = xmm_alpha; 2675 2676 while (height--) 2677 { 2678 int w = width; 2679 const uint32_t *pm = (uint32_t *)mask_line; 2680 uint32_t *pd = (uint32_t *)dst_line; 2681 2682 dst_line += dst_stride; 2683 mask_line += mask_stride; 2684 2685 while (w && (uintptr_t)pd & 15) 2686 { 2687 m = *pm++; 2688 2689 if (m) 2690 { 2691 d = *pd; 2692 mmx_mask = unpack_32_1x128 (m); 2693 mmx_dest = unpack_32_1x128 (d); 2694 2695 *pd = pack_1x128_32 (in_over_1x128 (&mmx_src, 2696 &mmx_alpha, 2697 &mmx_mask, 2698 &mmx_dest)); 2699 } 2700 2701 pd++; 2702 w--; 2703 } 2704 2705 while (w >= 4) 2706 { 2707 xmm_mask = load_128_unaligned ((__m128i*)pm); 2708 2709 pack_cmp = 2710 _mm_movemask_epi8 ( 2711 _mm_cmpeq_epi32 (xmm_mask, _mm_setzero_si128 ())); 2712 2713 /* if all bits in mask are zero, pack_cmp are equal to 0xffff */ 2714 if (pack_cmp != 0xffff) 2715 { 2716 xmm_dst = load_128_aligned ((__m128i*)pd); 2717 2718 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 2719 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 2720 2721 in_over_2x128 (&xmm_src, &xmm_src, 2722 &xmm_alpha, &xmm_alpha, 2723 &xmm_mask_lo, &xmm_mask_hi, 2724 &xmm_dst_lo, &xmm_dst_hi); 2725 2726 save_128_aligned ( 2727 (__m128i*)pd, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 2728 } 2729 2730 pd += 4; 2731 pm += 4; 2732 w -= 4; 2733 } 2734 2735 while (w) 2736 { 2737 m = *pm++; 2738 2739 if (m) 2740 { 2741 d = *pd; 2742 mmx_mask = unpack_32_1x128 (m); 2743 mmx_dest = unpack_32_1x128 (d); 2744 2745 *pd = pack_1x128_32 ( 2746 in_over_1x128 (&mmx_src, &mmx_alpha, &mmx_mask, &mmx_dest)); 2747 } 2748 2749 pd++; 2750 w--; 2751 } 2752 } 2753 2754 } 2755 2756 static void 2757 sse2_composite_over_8888_n_8888 (pixman_implementation_t *imp, 2758 pixman_composite_info_t *info) 2759 { 2760 PIXMAN_COMPOSITE_ARGS (info); 2761 uint32_t *dst_line, *dst; 2762 uint32_t *src_line, *src; 2763 uint32_t mask; 2764 int32_t w; 2765 int dst_stride, src_stride; 2766 2767 __m128i xmm_mask; 2768 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 2769 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 2770 __m128i xmm_alpha_lo, xmm_alpha_hi; 2771 2772 PIXMAN_IMAGE_GET_LINE ( 2773 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 2774 PIXMAN_IMAGE_GET_LINE ( 2775 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 2776 2777 mask = _pixman_image_get_solid (imp, mask_image, PIXMAN_a8r8g8b8); 2778 2779 xmm_mask = create_mask_16_128 (mask >> 24); 2780 2781 while (height--) 2782 { 2783 dst = dst_line; 2784 dst_line += dst_stride; 2785 src = src_line; 2786 src_line += src_stride; 2787 w = width; 2788 2789 while (w && (uintptr_t)dst & 15) 2790 { 2791 uint32_t s = *src++; 2792 2793 if (s) 2794 { 2795 uint32_t d = *dst; 2796 2797 __m128i ms = unpack_32_1x128 (s); 2798 __m128i alpha = expand_alpha_1x128 (ms); 2799 __m128i dest = xmm_mask; 2800 __m128i alpha_dst = unpack_32_1x128 (d); 2801 2802 *dst = pack_1x128_32 ( 2803 in_over_1x128 (&ms, &alpha, &dest, &alpha_dst)); 2804 } 2805 dst++; 2806 w--; 2807 } 2808 2809 while (w >= 4) 2810 { 2811 xmm_src = load_128_unaligned ((__m128i*)src); 2812 2813 if (!is_zero (xmm_src)) 2814 { 2815 xmm_dst = load_128_aligned ((__m128i*)dst); 2816 2817 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 2818 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 2819 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 2820 &xmm_alpha_lo, &xmm_alpha_hi); 2821 2822 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, 2823 &xmm_alpha_lo, &xmm_alpha_hi, 2824 &xmm_mask, &xmm_mask, 2825 &xmm_dst_lo, &xmm_dst_hi); 2826 2827 save_128_aligned ( 2828 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 2829 } 2830 2831 dst += 4; 2832 src += 4; 2833 w -= 4; 2834 } 2835 2836 while (w) 2837 { 2838 uint32_t s = *src++; 2839 2840 if (s) 2841 { 2842 uint32_t d = *dst; 2843 2844 __m128i ms = unpack_32_1x128 (s); 2845 __m128i alpha = expand_alpha_1x128 (ms); 2846 __m128i mask = xmm_mask; 2847 __m128i dest = unpack_32_1x128 (d); 2848 2849 *dst = pack_1x128_32 ( 2850 in_over_1x128 (&ms, &alpha, &mask, &dest)); 2851 } 2852 2853 dst++; 2854 w--; 2855 } 2856 } 2857 2858 } 2859 2860 static void 2861 sse2_composite_src_x888_0565 (pixman_implementation_t *imp, 2862 pixman_composite_info_t *info) 2863 { 2864 PIXMAN_COMPOSITE_ARGS (info); 2865 uint16_t *dst_line, *dst; 2866 uint32_t *src_line, *src, s; 2867 int dst_stride, src_stride; 2868 int32_t w; 2869 2870 PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 2871 PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); 2872 2873 while (height--) 2874 { 2875 dst = dst_line; 2876 dst_line += dst_stride; 2877 src = src_line; 2878 src_line += src_stride; 2879 w = width; 2880 2881 while (w && (uintptr_t)dst & 15) 2882 { 2883 s = *src++; 2884 *dst = convert_8888_to_0565 (s); 2885 dst++; 2886 w--; 2887 } 2888 2889 while (w >= 8) 2890 { 2891 __m128i xmm_src0 = load_128_unaligned ((__m128i *)src + 0); 2892 __m128i xmm_src1 = load_128_unaligned ((__m128i *)src + 1); 2893 2894 save_128_aligned ((__m128i*)dst, pack_565_2packedx128_128 (xmm_src0, xmm_src1)); 2895 2896 w -= 8; 2897 src += 8; 2898 dst += 8; 2899 } 2900 2901 while (w) 2902 { 2903 s = *src++; 2904 *dst = convert_8888_to_0565 (s); 2905 dst++; 2906 w--; 2907 } 2908 } 2909 } 2910 2911 static void 2912 sse2_composite_src_x888_8888 (pixman_implementation_t *imp, 2913 pixman_composite_info_t *info) 2914 { 2915 PIXMAN_COMPOSITE_ARGS (info); 2916 uint32_t *dst_line, *dst; 2917 uint32_t *src_line, *src; 2918 int32_t w; 2919 int dst_stride, src_stride; 2920 2921 2922 PIXMAN_IMAGE_GET_LINE ( 2923 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 2924 PIXMAN_IMAGE_GET_LINE ( 2925 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 2926 2927 while (height--) 2928 { 2929 dst = dst_line; 2930 dst_line += dst_stride; 2931 src = src_line; 2932 src_line += src_stride; 2933 w = width; 2934 2935 while (w && (uintptr_t)dst & 15) 2936 { 2937 *dst++ = *src++ | 0xff000000; 2938 w--; 2939 } 2940 2941 while (w >= 16) 2942 { 2943 __m128i xmm_src1, xmm_src2, xmm_src3, xmm_src4; 2944 2945 xmm_src1 = load_128_unaligned ((__m128i*)src + 0); 2946 xmm_src2 = load_128_unaligned ((__m128i*)src + 1); 2947 xmm_src3 = load_128_unaligned ((__m128i*)src + 2); 2948 xmm_src4 = load_128_unaligned ((__m128i*)src + 3); 2949 2950 save_128_aligned ((__m128i*)dst + 0, _mm_or_si128 (xmm_src1, mask_ff000000)); 2951 save_128_aligned ((__m128i*)dst + 1, _mm_or_si128 (xmm_src2, mask_ff000000)); 2952 save_128_aligned ((__m128i*)dst + 2, _mm_or_si128 (xmm_src3, mask_ff000000)); 2953 save_128_aligned ((__m128i*)dst + 3, _mm_or_si128 (xmm_src4, mask_ff000000)); 2954 2955 dst += 16; 2956 src += 16; 2957 w -= 16; 2958 } 2959 2960 while (w) 2961 { 2962 *dst++ = *src++ | 0xff000000; 2963 w--; 2964 } 2965 } 2966 2967 } 2968 2969 static void 2970 sse2_composite_over_x888_n_8888 (pixman_implementation_t *imp, 2971 pixman_composite_info_t *info) 2972 { 2973 PIXMAN_COMPOSITE_ARGS (info); 2974 uint32_t *dst_line, *dst; 2975 uint32_t *src_line, *src; 2976 uint32_t mask; 2977 int dst_stride, src_stride; 2978 int32_t w; 2979 2980 __m128i xmm_mask, xmm_alpha; 2981 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 2982 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 2983 2984 PIXMAN_IMAGE_GET_LINE ( 2985 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 2986 PIXMAN_IMAGE_GET_LINE ( 2987 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 2988 2989 mask = _pixman_image_get_solid (imp, mask_image, PIXMAN_a8r8g8b8); 2990 2991 xmm_mask = create_mask_16_128 (mask >> 24); 2992 xmm_alpha = mask_00ff; 2993 2994 while (height--) 2995 { 2996 dst = dst_line; 2997 dst_line += dst_stride; 2998 src = src_line; 2999 src_line += src_stride; 3000 w = width; 3001 3002 while (w && (uintptr_t)dst & 15) 3003 { 3004 uint32_t s = (*src++) | 0xff000000; 3005 uint32_t d = *dst; 3006 3007 __m128i src = unpack_32_1x128 (s); 3008 __m128i alpha = xmm_alpha; 3009 __m128i mask = xmm_mask; 3010 __m128i dest = unpack_32_1x128 (d); 3011 3012 *dst++ = pack_1x128_32 ( 3013 in_over_1x128 (&src, &alpha, &mask, &dest)); 3014 3015 w--; 3016 } 3017 3018 while (w >= 4) 3019 { 3020 xmm_src = _mm_or_si128 ( 3021 load_128_unaligned ((__m128i*)src), mask_ff000000); 3022 xmm_dst = load_128_aligned ((__m128i*)dst); 3023 3024 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 3025 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 3026 3027 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, 3028 &xmm_alpha, &xmm_alpha, 3029 &xmm_mask, &xmm_mask, 3030 &xmm_dst_lo, &xmm_dst_hi); 3031 3032 save_128_aligned ( 3033 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 3034 3035 dst += 4; 3036 src += 4; 3037 w -= 4; 3038 3039 } 3040 3041 while (w) 3042 { 3043 uint32_t s = (*src++) | 0xff000000; 3044 uint32_t d = *dst; 3045 3046 __m128i src = unpack_32_1x128 (s); 3047 __m128i alpha = xmm_alpha; 3048 __m128i mask = xmm_mask; 3049 __m128i dest = unpack_32_1x128 (d); 3050 3051 *dst++ = pack_1x128_32 ( 3052 in_over_1x128 (&src, &alpha, &mask, &dest)); 3053 3054 w--; 3055 } 3056 } 3057 3058 } 3059 3060 static void 3061 sse2_composite_over_8888_8888 (pixman_implementation_t *imp, 3062 pixman_composite_info_t *info) 3063 { 3064 PIXMAN_COMPOSITE_ARGS (info); 3065 int dst_stride, src_stride; 3066 uint32_t *dst_line, *dst; 3067 uint32_t *src_line, *src; 3068 3069 PIXMAN_IMAGE_GET_LINE ( 3070 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 3071 PIXMAN_IMAGE_GET_LINE ( 3072 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 3073 3074 dst = dst_line; 3075 src = src_line; 3076 3077 while (height--) 3078 { 3079 sse2_combine_over_u (imp, op, dst, src, NULL, width); 3080 3081 dst += dst_stride; 3082 src += src_stride; 3083 } 3084 } 3085 3086 static force_inline uint16_t 3087 composite_over_8888_0565pixel (uint32_t src, uint16_t dst) 3088 { 3089 __m128i ms; 3090 3091 ms = unpack_32_1x128 (src); 3092 return pack_565_32_16 ( 3093 pack_1x128_32 ( 3094 over_1x128 ( 3095 ms, expand_alpha_1x128 (ms), expand565_16_1x128 (dst)))); 3096 } 3097 3098 static void 3099 sse2_composite_over_8888_0565 (pixman_implementation_t *imp, 3100 pixman_composite_info_t *info) 3101 { 3102 PIXMAN_COMPOSITE_ARGS (info); 3103 uint16_t *dst_line, *dst, d; 3104 uint32_t *src_line, *src, s; 3105 int dst_stride, src_stride; 3106 int32_t w; 3107 3108 __m128i xmm_alpha_lo, xmm_alpha_hi; 3109 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 3110 __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3; 3111 3112 PIXMAN_IMAGE_GET_LINE ( 3113 dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); 3114 PIXMAN_IMAGE_GET_LINE ( 3115 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 3116 3117 while (height--) 3118 { 3119 dst = dst_line; 3120 src = src_line; 3121 3122 dst_line += dst_stride; 3123 src_line += src_stride; 3124 w = width; 3125 3126 /* Align dst on a 16-byte boundary */ 3127 while (w && 3128 ((uintptr_t)dst & 15)) 3129 { 3130 s = *src++; 3131 d = *dst; 3132 3133 *dst++ = composite_over_8888_0565pixel (s, d); 3134 w--; 3135 } 3136 3137 /* It's a 8 pixel loop */ 3138 while (w >= 8) 3139 { 3140 /* I'm loading unaligned because I'm not sure 3141 * about the address alignment. 3142 */ 3143 xmm_src = load_128_unaligned ((__m128i*) src); 3144 xmm_dst = load_128_aligned ((__m128i*) dst); 3145 3146 /* Unpacking */ 3147 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 3148 unpack_565_128_4x128 (xmm_dst, 3149 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3); 3150 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 3151 &xmm_alpha_lo, &xmm_alpha_hi); 3152 3153 /* I'm loading next 4 pixels from memory 3154 * before to optimze the memory read. 3155 */ 3156 xmm_src = load_128_unaligned ((__m128i*) (src + 4)); 3157 3158 over_2x128 (&xmm_src_lo, &xmm_src_hi, 3159 &xmm_alpha_lo, &xmm_alpha_hi, 3160 &xmm_dst0, &xmm_dst1); 3161 3162 /* Unpacking */ 3163 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 3164 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 3165 &xmm_alpha_lo, &xmm_alpha_hi); 3166 3167 over_2x128 (&xmm_src_lo, &xmm_src_hi, 3168 &xmm_alpha_lo, &xmm_alpha_hi, 3169 &xmm_dst2, &xmm_dst3); 3170 3171 save_128_aligned ( 3172 (__m128i*)dst, pack_565_4x128_128 ( 3173 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3)); 3174 3175 w -= 8; 3176 dst += 8; 3177 src += 8; 3178 } 3179 3180 while (w--) 3181 { 3182 s = *src++; 3183 d = *dst; 3184 3185 *dst++ = composite_over_8888_0565pixel (s, d); 3186 } 3187 } 3188 3189 } 3190 3191 static void 3192 sse2_composite_over_n_8_8888 (pixman_implementation_t *imp, 3193 pixman_composite_info_t *info) 3194 { 3195 PIXMAN_COMPOSITE_ARGS (info); 3196 uint32_t src, srca; 3197 uint32_t *dst_line, *dst; 3198 uint8_t *mask_line, *mask; 3199 int dst_stride, mask_stride; 3200 int32_t w; 3201 uint32_t m, d; 3202 3203 __m128i xmm_src, xmm_alpha, xmm_def; 3204 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 3205 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 3206 3207 __m128i mmx_src, mmx_alpha, mmx_mask, mmx_dest; 3208 3209 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 3210 3211 srca = src >> 24; 3212 if (src == 0) 3213 return; 3214 3215 PIXMAN_IMAGE_GET_LINE ( 3216 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 3217 PIXMAN_IMAGE_GET_LINE ( 3218 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 3219 3220 xmm_def = create_mask_2x32_128 (src, src); 3221 xmm_src = expand_pixel_32_1x128 (src); 3222 xmm_alpha = expand_alpha_1x128 (xmm_src); 3223 mmx_src = xmm_src; 3224 mmx_alpha = xmm_alpha; 3225 3226 while (height--) 3227 { 3228 dst = dst_line; 3229 dst_line += dst_stride; 3230 mask = mask_line; 3231 mask_line += mask_stride; 3232 w = width; 3233 3234 while (w && (uintptr_t)dst & 15) 3235 { 3236 uint8_t m = *mask++; 3237 3238 if (m) 3239 { 3240 d = *dst; 3241 mmx_mask = expand_pixel_8_1x128 (m); 3242 mmx_dest = unpack_32_1x128 (d); 3243 3244 *dst = pack_1x128_32 (in_over_1x128 (&mmx_src, 3245 &mmx_alpha, 3246 &mmx_mask, 3247 &mmx_dest)); 3248 } 3249 3250 w--; 3251 dst++; 3252 } 3253 3254 while (w >= 4) 3255 { 3256 m = *((uint32_t*)mask); 3257 3258 if (srca == 0xff && m == 0xffffffff) 3259 { 3260 save_128_aligned ((__m128i*)dst, xmm_def); 3261 } 3262 else if (m) 3263 { 3264 xmm_dst = load_128_aligned ((__m128i*) dst); 3265 xmm_mask = unpack_32_1x128 (m); 3266 xmm_mask = _mm_unpacklo_epi8 (xmm_mask, _mm_setzero_si128 ()); 3267 3268 /* Unpacking */ 3269 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 3270 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 3271 3272 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, 3273 &xmm_mask_lo, &xmm_mask_hi); 3274 3275 in_over_2x128 (&xmm_src, &xmm_src, 3276 &xmm_alpha, &xmm_alpha, 3277 &xmm_mask_lo, &xmm_mask_hi, 3278 &xmm_dst_lo, &xmm_dst_hi); 3279 3280 save_128_aligned ( 3281 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 3282 } 3283 3284 w -= 4; 3285 dst += 4; 3286 mask += 4; 3287 } 3288 3289 while (w) 3290 { 3291 uint8_t m = *mask++; 3292 3293 if (m) 3294 { 3295 d = *dst; 3296 mmx_mask = expand_pixel_8_1x128 (m); 3297 mmx_dest = unpack_32_1x128 (d); 3298 3299 *dst = pack_1x128_32 (in_over_1x128 (&mmx_src, 3300 &mmx_alpha, 3301 &mmx_mask, 3302 &mmx_dest)); 3303 } 3304 3305 w--; 3306 dst++; 3307 } 3308 } 3309 3310 } 3311 3312 #if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) 3313 __attribute__((__force_align_arg_pointer__)) 3314 #endif 3315 static pixman_bool_t 3316 sse2_fill (pixman_implementation_t *imp, 3317 uint32_t * bits, 3318 int stride, 3319 int bpp, 3320 int x, 3321 int y, 3322 int width, 3323 int height, 3324 uint32_t filler) 3325 { 3326 uint32_t byte_width; 3327 uint8_t *byte_line; 3328 3329 __m128i xmm_def; 3330 3331 if (bpp == 8) 3332 { 3333 uint8_t b; 3334 uint16_t w; 3335 3336 stride = stride * (int) sizeof (uint32_t) / 1; 3337 byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x); 3338 byte_width = width; 3339 stride *= 1; 3340 3341 b = filler & 0xff; 3342 w = (b << 8) | b; 3343 filler = (w << 16) | w; 3344 } 3345 else if (bpp == 16) 3346 { 3347 stride = stride * (int) sizeof (uint32_t) / 2; 3348 byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); 3349 byte_width = 2 * width; 3350 stride *= 2; 3351 3352 filler = (filler & 0xffff) * 0x00010001; 3353 } 3354 else if (bpp == 32) 3355 { 3356 stride = stride * (int) sizeof (uint32_t) / 4; 3357 byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x); 3358 byte_width = 4 * width; 3359 stride *= 4; 3360 } 3361 else 3362 { 3363 return FALSE; 3364 } 3365 3366 xmm_def = create_mask_2x32_128 (filler, filler); 3367 3368 while (height--) 3369 { 3370 int w; 3371 uint8_t *d = byte_line; 3372 byte_line += stride; 3373 w = byte_width; 3374 3375 if (w >= 1 && ((uintptr_t)d & 1)) 3376 { 3377 *(uint8_t *)d = filler; 3378 w -= 1; 3379 d += 1; 3380 } 3381 3382 while (w >= 2 && ((uintptr_t)d & 3)) 3383 { 3384 *(uint16_t *)d = filler; 3385 w -= 2; 3386 d += 2; 3387 } 3388 3389 while (w >= 4 && ((uintptr_t)d & 15)) 3390 { 3391 *(uint32_t *)d = filler; 3392 3393 w -= 4; 3394 d += 4; 3395 } 3396 3397 while (w >= 128) 3398 { 3399 save_128_aligned ((__m128i*)(d), xmm_def); 3400 save_128_aligned ((__m128i*)(d + 16), xmm_def); 3401 save_128_aligned ((__m128i*)(d + 32), xmm_def); 3402 save_128_aligned ((__m128i*)(d + 48), xmm_def); 3403 save_128_aligned ((__m128i*)(d + 64), xmm_def); 3404 save_128_aligned ((__m128i*)(d + 80), xmm_def); 3405 save_128_aligned ((__m128i*)(d + 96), xmm_def); 3406 save_128_aligned ((__m128i*)(d + 112), xmm_def); 3407 3408 d += 128; 3409 w -= 128; 3410 } 3411 3412 if (w >= 64) 3413 { 3414 save_128_aligned ((__m128i*)(d), xmm_def); 3415 save_128_aligned ((__m128i*)(d + 16), xmm_def); 3416 save_128_aligned ((__m128i*)(d + 32), xmm_def); 3417 save_128_aligned ((__m128i*)(d + 48), xmm_def); 3418 3419 d += 64; 3420 w -= 64; 3421 } 3422 3423 if (w >= 32) 3424 { 3425 save_128_aligned ((__m128i*)(d), xmm_def); 3426 save_128_aligned ((__m128i*)(d + 16), xmm_def); 3427 3428 d += 32; 3429 w -= 32; 3430 } 3431 3432 if (w >= 16) 3433 { 3434 save_128_aligned ((__m128i*)(d), xmm_def); 3435 3436 d += 16; 3437 w -= 16; 3438 } 3439 3440 while (w >= 4) 3441 { 3442 *(uint32_t *)d = filler; 3443 3444 w -= 4; 3445 d += 4; 3446 } 3447 3448 if (w >= 2) 3449 { 3450 *(uint16_t *)d = filler; 3451 w -= 2; 3452 d += 2; 3453 } 3454 3455 if (w >= 1) 3456 { 3457 *(uint8_t *)d = filler; 3458 w -= 1; 3459 d += 1; 3460 } 3461 } 3462 3463 return TRUE; 3464 } 3465 3466 static void 3467 sse2_composite_src_n_8_8888 (pixman_implementation_t *imp, 3468 pixman_composite_info_t *info) 3469 { 3470 PIXMAN_COMPOSITE_ARGS (info); 3471 uint32_t src, srca; 3472 uint32_t *dst_line, *dst; 3473 uint8_t *mask_line, *mask; 3474 int dst_stride, mask_stride; 3475 int32_t w; 3476 uint32_t m; 3477 3478 __m128i xmm_src, xmm_def; 3479 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 3480 3481 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 3482 3483 srca = src >> 24; 3484 if (src == 0) 3485 { 3486 sse2_fill (imp, dest_image->bits.bits, dest_image->bits.rowstride, 3487 PIXMAN_FORMAT_BPP (dest_image->bits.format), 3488 dest_x, dest_y, width, height, 0); 3489 return; 3490 } 3491 3492 PIXMAN_IMAGE_GET_LINE ( 3493 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 3494 PIXMAN_IMAGE_GET_LINE ( 3495 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 3496 3497 xmm_def = create_mask_2x32_128 (src, src); 3498 xmm_src = expand_pixel_32_1x128 (src); 3499 3500 while (height--) 3501 { 3502 dst = dst_line; 3503 dst_line += dst_stride; 3504 mask = mask_line; 3505 mask_line += mask_stride; 3506 w = width; 3507 3508 while (w && (uintptr_t)dst & 15) 3509 { 3510 uint8_t m = *mask++; 3511 3512 if (m) 3513 { 3514 *dst = pack_1x128_32 ( 3515 pix_multiply_1x128 (xmm_src, expand_pixel_8_1x128 (m))); 3516 } 3517 else 3518 { 3519 *dst = 0; 3520 } 3521 3522 w--; 3523 dst++; 3524 } 3525 3526 while (w >= 4) 3527 { 3528 m = *((uint32_t*)mask); 3529 3530 if (srca == 0xff && m == 0xffffffff) 3531 { 3532 save_128_aligned ((__m128i*)dst, xmm_def); 3533 } 3534 else if (m) 3535 { 3536 xmm_mask = unpack_32_1x128 (m); 3537 xmm_mask = _mm_unpacklo_epi8 (xmm_mask, _mm_setzero_si128 ()); 3538 3539 /* Unpacking */ 3540 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 3541 3542 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, 3543 &xmm_mask_lo, &xmm_mask_hi); 3544 3545 pix_multiply_2x128 (&xmm_src, &xmm_src, 3546 &xmm_mask_lo, &xmm_mask_hi, 3547 &xmm_mask_lo, &xmm_mask_hi); 3548 3549 save_128_aligned ( 3550 (__m128i*)dst, pack_2x128_128 (xmm_mask_lo, xmm_mask_hi)); 3551 } 3552 else 3553 { 3554 save_128_aligned ((__m128i*)dst, _mm_setzero_si128 ()); 3555 } 3556 3557 w -= 4; 3558 dst += 4; 3559 mask += 4; 3560 } 3561 3562 while (w) 3563 { 3564 uint8_t m = *mask++; 3565 3566 if (m) 3567 { 3568 *dst = pack_1x128_32 ( 3569 pix_multiply_1x128 ( 3570 xmm_src, expand_pixel_8_1x128 (m))); 3571 } 3572 else 3573 { 3574 *dst = 0; 3575 } 3576 3577 w--; 3578 dst++; 3579 } 3580 } 3581 3582 } 3583 3584 static void 3585 sse2_composite_over_n_8_0565 (pixman_implementation_t *imp, 3586 pixman_composite_info_t *info) 3587 { 3588 PIXMAN_COMPOSITE_ARGS (info); 3589 uint32_t src; 3590 uint16_t *dst_line, *dst, d; 3591 uint8_t *mask_line, *mask; 3592 int dst_stride, mask_stride; 3593 int32_t w; 3594 uint32_t m; 3595 __m128i mmx_src, mmx_alpha, mmx_mask, mmx_dest; 3596 3597 __m128i xmm_src, xmm_alpha; 3598 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 3599 __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3; 3600 3601 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 3602 3603 if (src == 0) 3604 return; 3605 3606 PIXMAN_IMAGE_GET_LINE ( 3607 dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); 3608 PIXMAN_IMAGE_GET_LINE ( 3609 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 3610 3611 xmm_src = expand_pixel_32_1x128 (src); 3612 xmm_alpha = expand_alpha_1x128 (xmm_src); 3613 mmx_src = xmm_src; 3614 mmx_alpha = xmm_alpha; 3615 3616 while (height--) 3617 { 3618 dst = dst_line; 3619 dst_line += dst_stride; 3620 mask = mask_line; 3621 mask_line += mask_stride; 3622 w = width; 3623 3624 while (w && (uintptr_t)dst & 15) 3625 { 3626 m = *mask++; 3627 3628 if (m) 3629 { 3630 d = *dst; 3631 mmx_mask = expand_alpha_rev_1x128 (unpack_32_1x128 (m)); 3632 mmx_dest = expand565_16_1x128 (d); 3633 3634 *dst = pack_565_32_16 ( 3635 pack_1x128_32 ( 3636 in_over_1x128 ( 3637 &mmx_src, &mmx_alpha, &mmx_mask, &mmx_dest))); 3638 } 3639 3640 w--; 3641 dst++; 3642 } 3643 3644 while (w >= 8) 3645 { 3646 xmm_dst = load_128_aligned ((__m128i*) dst); 3647 unpack_565_128_4x128 (xmm_dst, 3648 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3); 3649 3650 m = *((uint32_t*)mask); 3651 mask += 4; 3652 3653 if (m) 3654 { 3655 xmm_mask = unpack_32_1x128 (m); 3656 xmm_mask = _mm_unpacklo_epi8 (xmm_mask, _mm_setzero_si128 ()); 3657 3658 /* Unpacking */ 3659 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 3660 3661 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, 3662 &xmm_mask_lo, &xmm_mask_hi); 3663 3664 in_over_2x128 (&xmm_src, &xmm_src, 3665 &xmm_alpha, &xmm_alpha, 3666 &xmm_mask_lo, &xmm_mask_hi, 3667 &xmm_dst0, &xmm_dst1); 3668 } 3669 3670 m = *((uint32_t*)mask); 3671 mask += 4; 3672 3673 if (m) 3674 { 3675 xmm_mask = unpack_32_1x128 (m); 3676 xmm_mask = _mm_unpacklo_epi8 (xmm_mask, _mm_setzero_si128 ()); 3677 3678 /* Unpacking */ 3679 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 3680 3681 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, 3682 &xmm_mask_lo, &xmm_mask_hi); 3683 in_over_2x128 (&xmm_src, &xmm_src, 3684 &xmm_alpha, &xmm_alpha, 3685 &xmm_mask_lo, &xmm_mask_hi, 3686 &xmm_dst2, &xmm_dst3); 3687 } 3688 3689 save_128_aligned ( 3690 (__m128i*)dst, pack_565_4x128_128 ( 3691 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3)); 3692 3693 w -= 8; 3694 dst += 8; 3695 } 3696 3697 while (w) 3698 { 3699 m = *mask++; 3700 3701 if (m) 3702 { 3703 d = *dst; 3704 mmx_mask = expand_alpha_rev_1x128 (unpack_32_1x128 (m)); 3705 mmx_dest = expand565_16_1x128 (d); 3706 3707 *dst = pack_565_32_16 ( 3708 pack_1x128_32 ( 3709 in_over_1x128 ( 3710 &mmx_src, &mmx_alpha, &mmx_mask, &mmx_dest))); 3711 } 3712 3713 w--; 3714 dst++; 3715 } 3716 } 3717 3718 } 3719 3720 static void 3721 sse2_composite_over_pixbuf_0565 (pixman_implementation_t *imp, 3722 pixman_composite_info_t *info) 3723 { 3724 PIXMAN_COMPOSITE_ARGS (info); 3725 uint16_t *dst_line, *dst, d; 3726 uint32_t *src_line, *src, s; 3727 int dst_stride, src_stride; 3728 int32_t w; 3729 uint32_t opaque, zero; 3730 3731 __m128i ms; 3732 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 3733 __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3; 3734 3735 PIXMAN_IMAGE_GET_LINE ( 3736 dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); 3737 PIXMAN_IMAGE_GET_LINE ( 3738 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 3739 3740 while (height--) 3741 { 3742 dst = dst_line; 3743 dst_line += dst_stride; 3744 src = src_line; 3745 src_line += src_stride; 3746 w = width; 3747 3748 while (w && (uintptr_t)dst & 15) 3749 { 3750 s = *src++; 3751 d = *dst; 3752 3753 ms = unpack_32_1x128 (s); 3754 3755 *dst++ = pack_565_32_16 ( 3756 pack_1x128_32 ( 3757 over_rev_non_pre_1x128 (ms, expand565_16_1x128 (d)))); 3758 w--; 3759 } 3760 3761 while (w >= 8) 3762 { 3763 /* First round */ 3764 xmm_src = load_128_unaligned ((__m128i*)src); 3765 xmm_dst = load_128_aligned ((__m128i*)dst); 3766 3767 opaque = is_opaque (xmm_src); 3768 zero = is_zero (xmm_src); 3769 3770 unpack_565_128_4x128 (xmm_dst, 3771 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3); 3772 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 3773 3774 /* preload next round*/ 3775 xmm_src = load_128_unaligned ((__m128i*)(src + 4)); 3776 3777 if (opaque) 3778 { 3779 invert_colors_2x128 (xmm_src_lo, xmm_src_hi, 3780 &xmm_dst0, &xmm_dst1); 3781 } 3782 else if (!zero) 3783 { 3784 over_rev_non_pre_2x128 (xmm_src_lo, xmm_src_hi, 3785 &xmm_dst0, &xmm_dst1); 3786 } 3787 3788 /* Second round */ 3789 opaque = is_opaque (xmm_src); 3790 zero = is_zero (xmm_src); 3791 3792 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 3793 3794 if (opaque) 3795 { 3796 invert_colors_2x128 (xmm_src_lo, xmm_src_hi, 3797 &xmm_dst2, &xmm_dst3); 3798 } 3799 else if (!zero) 3800 { 3801 over_rev_non_pre_2x128 (xmm_src_lo, xmm_src_hi, 3802 &xmm_dst2, &xmm_dst3); 3803 } 3804 3805 save_128_aligned ( 3806 (__m128i*)dst, pack_565_4x128_128 ( 3807 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3)); 3808 3809 w -= 8; 3810 src += 8; 3811 dst += 8; 3812 } 3813 3814 while (w) 3815 { 3816 s = *src++; 3817 d = *dst; 3818 3819 ms = unpack_32_1x128 (s); 3820 3821 *dst++ = pack_565_32_16 ( 3822 pack_1x128_32 ( 3823 over_rev_non_pre_1x128 (ms, expand565_16_1x128 (d)))); 3824 w--; 3825 } 3826 } 3827 3828 } 3829 3830 static void 3831 sse2_composite_over_pixbuf_8888 (pixman_implementation_t *imp, 3832 pixman_composite_info_t *info) 3833 { 3834 PIXMAN_COMPOSITE_ARGS (info); 3835 uint32_t *dst_line, *dst, d; 3836 uint32_t *src_line, *src, s; 3837 int dst_stride, src_stride; 3838 int32_t w; 3839 uint32_t opaque, zero; 3840 3841 __m128i xmm_src_lo, xmm_src_hi; 3842 __m128i xmm_dst_lo, xmm_dst_hi; 3843 3844 PIXMAN_IMAGE_GET_LINE ( 3845 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 3846 PIXMAN_IMAGE_GET_LINE ( 3847 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 3848 3849 while (height--) 3850 { 3851 dst = dst_line; 3852 dst_line += dst_stride; 3853 src = src_line; 3854 src_line += src_stride; 3855 w = width; 3856 3857 while (w && (uintptr_t)dst & 15) 3858 { 3859 s = *src++; 3860 d = *dst; 3861 3862 *dst++ = pack_1x128_32 ( 3863 over_rev_non_pre_1x128 ( 3864 unpack_32_1x128 (s), unpack_32_1x128 (d))); 3865 3866 w--; 3867 } 3868 3869 while (w >= 4) 3870 { 3871 xmm_src_hi = load_128_unaligned ((__m128i*)src); 3872 3873 opaque = is_opaque (xmm_src_hi); 3874 zero = is_zero (xmm_src_hi); 3875 3876 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 3877 3878 if (opaque) 3879 { 3880 invert_colors_2x128 (xmm_src_lo, xmm_src_hi, 3881 &xmm_dst_lo, &xmm_dst_hi); 3882 3883 save_128_aligned ( 3884 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 3885 } 3886 else if (!zero) 3887 { 3888 xmm_dst_hi = load_128_aligned ((__m128i*)dst); 3889 3890 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 3891 3892 over_rev_non_pre_2x128 (xmm_src_lo, xmm_src_hi, 3893 &xmm_dst_lo, &xmm_dst_hi); 3894 3895 save_128_aligned ( 3896 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 3897 } 3898 3899 w -= 4; 3900 dst += 4; 3901 src += 4; 3902 } 3903 3904 while (w) 3905 { 3906 s = *src++; 3907 d = *dst; 3908 3909 *dst++ = pack_1x128_32 ( 3910 over_rev_non_pre_1x128 ( 3911 unpack_32_1x128 (s), unpack_32_1x128 (d))); 3912 3913 w--; 3914 } 3915 } 3916 3917 } 3918 3919 static void 3920 sse2_composite_over_n_8888_0565_ca (pixman_implementation_t *imp, 3921 pixman_composite_info_t *info) 3922 { 3923 PIXMAN_COMPOSITE_ARGS (info); 3924 uint32_t src; 3925 uint16_t *dst_line, *dst, d; 3926 uint32_t *mask_line, *mask, m; 3927 int dst_stride, mask_stride; 3928 int w; 3929 uint32_t pack_cmp; 3930 3931 __m128i xmm_src, xmm_alpha; 3932 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 3933 __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3; 3934 3935 __m128i mmx_src, mmx_alpha, mmx_mask, mmx_dest; 3936 3937 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 3938 3939 if (src == 0) 3940 return; 3941 3942 PIXMAN_IMAGE_GET_LINE ( 3943 dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); 3944 PIXMAN_IMAGE_GET_LINE ( 3945 mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1); 3946 3947 xmm_src = expand_pixel_32_1x128 (src); 3948 xmm_alpha = expand_alpha_1x128 (xmm_src); 3949 mmx_src = xmm_src; 3950 mmx_alpha = xmm_alpha; 3951 3952 while (height--) 3953 { 3954 w = width; 3955 mask = mask_line; 3956 dst = dst_line; 3957 mask_line += mask_stride; 3958 dst_line += dst_stride; 3959 3960 while (w && ((uintptr_t)dst & 15)) 3961 { 3962 m = *(uint32_t *) mask; 3963 3964 if (m) 3965 { 3966 d = *dst; 3967 mmx_mask = unpack_32_1x128 (m); 3968 mmx_dest = expand565_16_1x128 (d); 3969 3970 *dst = pack_565_32_16 ( 3971 pack_1x128_32 ( 3972 in_over_1x128 ( 3973 &mmx_src, &mmx_alpha, &mmx_mask, &mmx_dest))); 3974 } 3975 3976 w--; 3977 dst++; 3978 mask++; 3979 } 3980 3981 while (w >= 8) 3982 { 3983 /* First round */ 3984 xmm_mask = load_128_unaligned ((__m128i*)mask); 3985 xmm_dst = load_128_aligned ((__m128i*)dst); 3986 3987 pack_cmp = _mm_movemask_epi8 ( 3988 _mm_cmpeq_epi32 (xmm_mask, _mm_setzero_si128 ())); 3989 3990 unpack_565_128_4x128 (xmm_dst, 3991 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3); 3992 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 3993 3994 /* preload next round */ 3995 xmm_mask = load_128_unaligned ((__m128i*)(mask + 4)); 3996 3997 /* preload next round */ 3998 if (pack_cmp != 0xffff) 3999 { 4000 in_over_2x128 (&xmm_src, &xmm_src, 4001 &xmm_alpha, &xmm_alpha, 4002 &xmm_mask_lo, &xmm_mask_hi, 4003 &xmm_dst0, &xmm_dst1); 4004 } 4005 4006 /* Second round */ 4007 pack_cmp = _mm_movemask_epi8 ( 4008 _mm_cmpeq_epi32 (xmm_mask, _mm_setzero_si128 ())); 4009 4010 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 4011 4012 if (pack_cmp != 0xffff) 4013 { 4014 in_over_2x128 (&xmm_src, &xmm_src, 4015 &xmm_alpha, &xmm_alpha, 4016 &xmm_mask_lo, &xmm_mask_hi, 4017 &xmm_dst2, &xmm_dst3); 4018 } 4019 4020 save_128_aligned ( 4021 (__m128i*)dst, pack_565_4x128_128 ( 4022 &xmm_dst0, &xmm_dst1, &xmm_dst2, &xmm_dst3)); 4023 4024 w -= 8; 4025 dst += 8; 4026 mask += 8; 4027 } 4028 4029 while (w) 4030 { 4031 m = *(uint32_t *) mask; 4032 4033 if (m) 4034 { 4035 d = *dst; 4036 mmx_mask = unpack_32_1x128 (m); 4037 mmx_dest = expand565_16_1x128 (d); 4038 4039 *dst = pack_565_32_16 ( 4040 pack_1x128_32 ( 4041 in_over_1x128 ( 4042 &mmx_src, &mmx_alpha, &mmx_mask, &mmx_dest))); 4043 } 4044 4045 w--; 4046 dst++; 4047 mask++; 4048 } 4049 } 4050 4051 } 4052 4053 static void 4054 sse2_composite_in_n_8_8 (pixman_implementation_t *imp, 4055 pixman_composite_info_t *info) 4056 { 4057 PIXMAN_COMPOSITE_ARGS (info); 4058 uint8_t *dst_line, *dst; 4059 uint8_t *mask_line, *mask; 4060 int dst_stride, mask_stride; 4061 uint32_t d, m; 4062 uint32_t src; 4063 int32_t w; 4064 4065 __m128i xmm_alpha; 4066 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 4067 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 4068 4069 PIXMAN_IMAGE_GET_LINE ( 4070 dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); 4071 PIXMAN_IMAGE_GET_LINE ( 4072 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 4073 4074 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 4075 4076 xmm_alpha = expand_alpha_1x128 (expand_pixel_32_1x128 (src)); 4077 4078 while (height--) 4079 { 4080 dst = dst_line; 4081 dst_line += dst_stride; 4082 mask = mask_line; 4083 mask_line += mask_stride; 4084 w = width; 4085 4086 while (w && ((uintptr_t)dst & 15)) 4087 { 4088 m = (uint32_t) *mask++; 4089 d = (uint32_t) *dst; 4090 4091 *dst++ = (uint8_t) pack_1x128_32 ( 4092 pix_multiply_1x128 ( 4093 pix_multiply_1x128 (xmm_alpha, 4094 unpack_32_1x128 (m)), 4095 unpack_32_1x128 (d))); 4096 w--; 4097 } 4098 4099 while (w >= 16) 4100 { 4101 xmm_mask = load_128_unaligned ((__m128i*)mask); 4102 xmm_dst = load_128_aligned ((__m128i*)dst); 4103 4104 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 4105 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 4106 4107 pix_multiply_2x128 (&xmm_alpha, &xmm_alpha, 4108 &xmm_mask_lo, &xmm_mask_hi, 4109 &xmm_mask_lo, &xmm_mask_hi); 4110 4111 pix_multiply_2x128 (&xmm_mask_lo, &xmm_mask_hi, 4112 &xmm_dst_lo, &xmm_dst_hi, 4113 &xmm_dst_lo, &xmm_dst_hi); 4114 4115 save_128_aligned ( 4116 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 4117 4118 mask += 16; 4119 dst += 16; 4120 w -= 16; 4121 } 4122 4123 while (w) 4124 { 4125 m = (uint32_t) *mask++; 4126 d = (uint32_t) *dst; 4127 4128 *dst++ = (uint8_t) pack_1x128_32 ( 4129 pix_multiply_1x128 ( 4130 pix_multiply_1x128 ( 4131 xmm_alpha, unpack_32_1x128 (m)), 4132 unpack_32_1x128 (d))); 4133 w--; 4134 } 4135 } 4136 4137 } 4138 4139 static void 4140 sse2_composite_in_n_8 (pixman_implementation_t *imp, 4141 pixman_composite_info_t *info) 4142 { 4143 PIXMAN_COMPOSITE_ARGS (info); 4144 uint8_t *dst_line, *dst; 4145 int dst_stride; 4146 uint32_t d; 4147 uint32_t src; 4148 int32_t w; 4149 4150 __m128i xmm_alpha; 4151 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 4152 4153 PIXMAN_IMAGE_GET_LINE ( 4154 dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); 4155 4156 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 4157 4158 xmm_alpha = expand_alpha_1x128 (expand_pixel_32_1x128 (src)); 4159 4160 src = src >> 24; 4161 4162 if (src == 0xff) 4163 return; 4164 4165 if (src == 0x00) 4166 { 4167 pixman_fill (dest_image->bits.bits, dest_image->bits.rowstride, 4168 8, dest_x, dest_y, width, height, src); 4169 4170 return; 4171 } 4172 4173 while (height--) 4174 { 4175 dst = dst_line; 4176 dst_line += dst_stride; 4177 w = width; 4178 4179 while (w && ((uintptr_t)dst & 15)) 4180 { 4181 d = (uint32_t) *dst; 4182 4183 *dst++ = (uint8_t) pack_1x128_32 ( 4184 pix_multiply_1x128 ( 4185 xmm_alpha, 4186 unpack_32_1x128 (d))); 4187 w--; 4188 } 4189 4190 while (w >= 16) 4191 { 4192 xmm_dst = load_128_aligned ((__m128i*)dst); 4193 4194 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 4195 4196 pix_multiply_2x128 (&xmm_alpha, &xmm_alpha, 4197 &xmm_dst_lo, &xmm_dst_hi, 4198 &xmm_dst_lo, &xmm_dst_hi); 4199 4200 save_128_aligned ( 4201 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 4202 4203 dst += 16; 4204 w -= 16; 4205 } 4206 4207 while (w) 4208 { 4209 d = (uint32_t) *dst; 4210 4211 *dst++ = (uint8_t) pack_1x128_32 ( 4212 pix_multiply_1x128 ( 4213 xmm_alpha, 4214 unpack_32_1x128 (d))); 4215 w--; 4216 } 4217 } 4218 4219 } 4220 4221 static void 4222 sse2_composite_in_8_8 (pixman_implementation_t *imp, 4223 pixman_composite_info_t *info) 4224 { 4225 PIXMAN_COMPOSITE_ARGS (info); 4226 uint8_t *dst_line, *dst; 4227 uint8_t *src_line, *src; 4228 int src_stride, dst_stride; 4229 int32_t w; 4230 uint32_t s, d; 4231 4232 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 4233 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 4234 4235 PIXMAN_IMAGE_GET_LINE ( 4236 dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); 4237 PIXMAN_IMAGE_GET_LINE ( 4238 src_image, src_x, src_y, uint8_t, src_stride, src_line, 1); 4239 4240 while (height--) 4241 { 4242 dst = dst_line; 4243 dst_line += dst_stride; 4244 src = src_line; 4245 src_line += src_stride; 4246 w = width; 4247 4248 while (w && ((uintptr_t)dst & 15)) 4249 { 4250 s = (uint32_t) *src++; 4251 d = (uint32_t) *dst; 4252 4253 *dst++ = (uint8_t) pack_1x128_32 ( 4254 pix_multiply_1x128 ( 4255 unpack_32_1x128 (s), unpack_32_1x128 (d))); 4256 w--; 4257 } 4258 4259 while (w >= 16) 4260 { 4261 xmm_src = load_128_unaligned ((__m128i*)src); 4262 xmm_dst = load_128_aligned ((__m128i*)dst); 4263 4264 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 4265 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 4266 4267 pix_multiply_2x128 (&xmm_src_lo, &xmm_src_hi, 4268 &xmm_dst_lo, &xmm_dst_hi, 4269 &xmm_dst_lo, &xmm_dst_hi); 4270 4271 save_128_aligned ( 4272 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 4273 4274 src += 16; 4275 dst += 16; 4276 w -= 16; 4277 } 4278 4279 while (w) 4280 { 4281 s = (uint32_t) *src++; 4282 d = (uint32_t) *dst; 4283 4284 *dst++ = (uint8_t) pack_1x128_32 ( 4285 pix_multiply_1x128 (unpack_32_1x128 (s), unpack_32_1x128 (d))); 4286 w--; 4287 } 4288 } 4289 4290 } 4291 4292 static void 4293 sse2_composite_add_n_8_8 (pixman_implementation_t *imp, 4294 pixman_composite_info_t *info) 4295 { 4296 PIXMAN_COMPOSITE_ARGS (info); 4297 uint8_t *dst_line, *dst; 4298 uint8_t *mask_line, *mask; 4299 int dst_stride, mask_stride; 4300 int32_t w; 4301 uint32_t src; 4302 uint32_t m, d; 4303 4304 __m128i xmm_alpha; 4305 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 4306 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 4307 4308 PIXMAN_IMAGE_GET_LINE ( 4309 dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); 4310 PIXMAN_IMAGE_GET_LINE ( 4311 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 4312 4313 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 4314 4315 xmm_alpha = expand_alpha_1x128 (expand_pixel_32_1x128 (src)); 4316 4317 while (height--) 4318 { 4319 dst = dst_line; 4320 dst_line += dst_stride; 4321 mask = mask_line; 4322 mask_line += mask_stride; 4323 w = width; 4324 4325 while (w && ((uintptr_t)dst & 15)) 4326 { 4327 m = (uint32_t) *mask++; 4328 d = (uint32_t) *dst; 4329 4330 *dst++ = (uint8_t) pack_1x128_32 ( 4331 _mm_adds_epu16 ( 4332 pix_multiply_1x128 ( 4333 xmm_alpha, unpack_32_1x128 (m)), 4334 unpack_32_1x128 (d))); 4335 w--; 4336 } 4337 4338 while (w >= 16) 4339 { 4340 xmm_mask = load_128_unaligned ((__m128i*)mask); 4341 xmm_dst = load_128_aligned ((__m128i*)dst); 4342 4343 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 4344 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 4345 4346 pix_multiply_2x128 (&xmm_alpha, &xmm_alpha, 4347 &xmm_mask_lo, &xmm_mask_hi, 4348 &xmm_mask_lo, &xmm_mask_hi); 4349 4350 xmm_dst_lo = _mm_adds_epu16 (xmm_mask_lo, xmm_dst_lo); 4351 xmm_dst_hi = _mm_adds_epu16 (xmm_mask_hi, xmm_dst_hi); 4352 4353 save_128_aligned ( 4354 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 4355 4356 mask += 16; 4357 dst += 16; 4358 w -= 16; 4359 } 4360 4361 while (w) 4362 { 4363 m = (uint32_t) *mask++; 4364 d = (uint32_t) *dst; 4365 4366 *dst++ = (uint8_t) pack_1x128_32 ( 4367 _mm_adds_epu16 ( 4368 pix_multiply_1x128 ( 4369 xmm_alpha, unpack_32_1x128 (m)), 4370 unpack_32_1x128 (d))); 4371 4372 w--; 4373 } 4374 } 4375 4376 } 4377 4378 static void 4379 sse2_composite_add_n_8 (pixman_implementation_t *imp, 4380 pixman_composite_info_t *info) 4381 { 4382 PIXMAN_COMPOSITE_ARGS (info); 4383 uint8_t *dst_line, *dst; 4384 int dst_stride; 4385 int32_t w; 4386 uint32_t src; 4387 4388 __m128i xmm_src; 4389 4390 PIXMAN_IMAGE_GET_LINE ( 4391 dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); 4392 4393 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 4394 4395 src >>= 24; 4396 4397 if (src == 0x00) 4398 return; 4399 4400 if (src == 0xff) 4401 { 4402 pixman_fill (dest_image->bits.bits, dest_image->bits.rowstride, 4403 8, dest_x, dest_y, width, height, 0xff); 4404 4405 return; 4406 } 4407 4408 src = (src << 24) | (src << 16) | (src << 8) | src; 4409 xmm_src = _mm_set_epi32 (src, src, src, src); 4410 4411 while (height--) 4412 { 4413 dst = dst_line; 4414 dst_line += dst_stride; 4415 w = width; 4416 4417 while (w && ((uintptr_t)dst & 15)) 4418 { 4419 *dst = (uint8_t)_mm_cvtsi128_si32 ( 4420 _mm_adds_epu8 ( 4421 xmm_src, 4422 _mm_cvtsi32_si128 (*dst))); 4423 4424 w--; 4425 dst++; 4426 } 4427 4428 while (w >= 16) 4429 { 4430 save_128_aligned ( 4431 (__m128i*)dst, _mm_adds_epu8 (xmm_src, load_128_aligned ((__m128i*)dst))); 4432 4433 dst += 16; 4434 w -= 16; 4435 } 4436 4437 while (w) 4438 { 4439 *dst = (uint8_t)_mm_cvtsi128_si32 ( 4440 _mm_adds_epu8 ( 4441 xmm_src, 4442 _mm_cvtsi32_si128 (*dst))); 4443 4444 w--; 4445 dst++; 4446 } 4447 } 4448 4449 } 4450 4451 static void 4452 sse2_composite_add_8_8 (pixman_implementation_t *imp, 4453 pixman_composite_info_t *info) 4454 { 4455 PIXMAN_COMPOSITE_ARGS (info); 4456 uint8_t *dst_line, *dst; 4457 uint8_t *src_line, *src; 4458 int dst_stride, src_stride; 4459 int32_t w; 4460 uint16_t t; 4461 4462 PIXMAN_IMAGE_GET_LINE ( 4463 src_image, src_x, src_y, uint8_t, src_stride, src_line, 1); 4464 PIXMAN_IMAGE_GET_LINE ( 4465 dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); 4466 4467 while (height--) 4468 { 4469 dst = dst_line; 4470 src = src_line; 4471 4472 dst_line += dst_stride; 4473 src_line += src_stride; 4474 w = width; 4475 4476 /* Small head */ 4477 while (w && (uintptr_t)dst & 3) 4478 { 4479 t = (*dst) + (*src++); 4480 *dst++ = t | (0 - (t >> 8)); 4481 w--; 4482 } 4483 4484 sse2_combine_add_u (imp, op, 4485 (uint32_t*)dst, (uint32_t*)src, NULL, w >> 2); 4486 4487 /* Small tail */ 4488 dst += w & 0xfffc; 4489 src += w & 0xfffc; 4490 4491 w &= 3; 4492 4493 while (w) 4494 { 4495 t = (*dst) + (*src++); 4496 *dst++ = t | (0 - (t >> 8)); 4497 w--; 4498 } 4499 } 4500 4501 } 4502 4503 static void 4504 sse2_composite_add_8888_8888 (pixman_implementation_t *imp, 4505 pixman_composite_info_t *info) 4506 { 4507 PIXMAN_COMPOSITE_ARGS (info); 4508 uint32_t *dst_line, *dst; 4509 uint32_t *src_line, *src; 4510 int dst_stride, src_stride; 4511 4512 PIXMAN_IMAGE_GET_LINE ( 4513 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 4514 PIXMAN_IMAGE_GET_LINE ( 4515 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 4516 4517 while (height--) 4518 { 4519 dst = dst_line; 4520 dst_line += dst_stride; 4521 src = src_line; 4522 src_line += src_stride; 4523 4524 sse2_combine_add_u (imp, op, dst, src, NULL, width); 4525 } 4526 } 4527 4528 static void 4529 sse2_composite_add_n_8888 (pixman_implementation_t *imp, 4530 pixman_composite_info_t *info) 4531 { 4532 PIXMAN_COMPOSITE_ARGS (info); 4533 uint32_t *dst_line, *dst, src; 4534 int dst_stride; 4535 4536 __m128i xmm_src; 4537 4538 PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 4539 4540 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 4541 if (src == 0) 4542 return; 4543 4544 if (src == ~0) 4545 { 4546 pixman_fill (dest_image->bits.bits, dest_image->bits.rowstride, 32, 4547 dest_x, dest_y, width, height, ~0); 4548 4549 return; 4550 } 4551 4552 xmm_src = _mm_set_epi32 (src, src, src, src); 4553 while (height--) 4554 { 4555 int w = width; 4556 uint32_t d; 4557 4558 dst = dst_line; 4559 dst_line += dst_stride; 4560 4561 while (w && (uintptr_t)dst & 15) 4562 { 4563 d = *dst; 4564 *dst++ = 4565 _mm_cvtsi128_si32 ( _mm_adds_epu8 (xmm_src, _mm_cvtsi32_si128 (d))); 4566 w--; 4567 } 4568 4569 while (w >= 4) 4570 { 4571 save_128_aligned 4572 ((__m128i*)dst, 4573 _mm_adds_epu8 (xmm_src, load_128_aligned ((__m128i*)dst))); 4574 4575 dst += 4; 4576 w -= 4; 4577 } 4578 4579 while (w--) 4580 { 4581 d = *dst; 4582 *dst++ = 4583 _mm_cvtsi128_si32 (_mm_adds_epu8 (xmm_src, 4584 _mm_cvtsi32_si128 (d))); 4585 } 4586 } 4587 } 4588 4589 static void 4590 sse2_composite_add_n_8_8888 (pixman_implementation_t *imp, 4591 pixman_composite_info_t *info) 4592 { 4593 PIXMAN_COMPOSITE_ARGS (info); 4594 uint32_t *dst_line, *dst; 4595 uint8_t *mask_line, *mask; 4596 int dst_stride, mask_stride; 4597 int32_t w; 4598 uint32_t src; 4599 4600 __m128i xmm_src; 4601 4602 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 4603 if (src == 0) 4604 return; 4605 xmm_src = expand_pixel_32_1x128 (src); 4606 4607 PIXMAN_IMAGE_GET_LINE ( 4608 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 4609 PIXMAN_IMAGE_GET_LINE ( 4610 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 4611 4612 while (height--) 4613 { 4614 dst = dst_line; 4615 dst_line += dst_stride; 4616 mask = mask_line; 4617 mask_line += mask_stride; 4618 w = width; 4619 4620 while (w && ((uintptr_t)dst & 15)) 4621 { 4622 uint8_t m = *mask++; 4623 if (m) 4624 { 4625 *dst = pack_1x128_32 4626 (_mm_adds_epu16 4627 (pix_multiply_1x128 (xmm_src, expand_pixel_8_1x128 (m)), 4628 unpack_32_1x128 (*dst))); 4629 } 4630 dst++; 4631 w--; 4632 } 4633 4634 while (w >= 4) 4635 { 4636 uint32_t m = *(uint32_t*)mask; 4637 if (m) 4638 { 4639 __m128i xmm_mask_lo, xmm_mask_hi; 4640 __m128i xmm_dst_lo, xmm_dst_hi; 4641 4642 __m128i xmm_dst = load_128_aligned ((__m128i*)dst); 4643 __m128i xmm_mask = 4644 _mm_unpacklo_epi8 (unpack_32_1x128(m), 4645 _mm_setzero_si128 ()); 4646 4647 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 4648 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 4649 4650 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, 4651 &xmm_mask_lo, &xmm_mask_hi); 4652 4653 pix_multiply_2x128 (&xmm_src, &xmm_src, 4654 &xmm_mask_lo, &xmm_mask_hi, 4655 &xmm_mask_lo, &xmm_mask_hi); 4656 4657 xmm_dst_lo = _mm_adds_epu16 (xmm_mask_lo, xmm_dst_lo); 4658 xmm_dst_hi = _mm_adds_epu16 (xmm_mask_hi, xmm_dst_hi); 4659 4660 save_128_aligned ( 4661 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 4662 } 4663 4664 w -= 4; 4665 dst += 4; 4666 mask += 4; 4667 } 4668 4669 while (w) 4670 { 4671 uint8_t m = *mask++; 4672 if (m) 4673 { 4674 *dst = pack_1x128_32 4675 (_mm_adds_epu16 4676 (pix_multiply_1x128 (xmm_src, expand_pixel_8_1x128 (m)), 4677 unpack_32_1x128 (*dst))); 4678 } 4679 dst++; 4680 w--; 4681 } 4682 } 4683 } 4684 4685 static pixman_bool_t 4686 sse2_blt (pixman_implementation_t *imp, 4687 uint32_t * src_bits, 4688 uint32_t * dst_bits, 4689 int src_stride, 4690 int dst_stride, 4691 int src_bpp, 4692 int dst_bpp, 4693 int src_x, 4694 int src_y, 4695 int dest_x, 4696 int dest_y, 4697 int width, 4698 int height) 4699 { 4700 uint8_t * src_bytes; 4701 uint8_t * dst_bytes; 4702 int byte_width; 4703 4704 if (src_bpp != dst_bpp) 4705 return FALSE; 4706 4707 if (src_bpp == 16) 4708 { 4709 src_stride = src_stride * (int) sizeof (uint32_t) / 2; 4710 dst_stride = dst_stride * (int) sizeof (uint32_t) / 2; 4711 src_bytes =(uint8_t *)(((uint16_t *)src_bits) + src_stride * (src_y) + (src_x)); 4712 dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + dst_stride * (dest_y) + (dest_x)); 4713 byte_width = 2 * width; 4714 src_stride *= 2; 4715 dst_stride *= 2; 4716 } 4717 else if (src_bpp == 32) 4718 { 4719 src_stride = src_stride * (int) sizeof (uint32_t) / 4; 4720 dst_stride = dst_stride * (int) sizeof (uint32_t) / 4; 4721 src_bytes = (uint8_t *)(((uint32_t *)src_bits) + src_stride * (src_y) + (src_x)); 4722 dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + dst_stride * (dest_y) + (dest_x)); 4723 byte_width = 4 * width; 4724 src_stride *= 4; 4725 dst_stride *= 4; 4726 } 4727 else 4728 { 4729 return FALSE; 4730 } 4731 4732 while (height--) 4733 { 4734 int w; 4735 uint8_t *s = src_bytes; 4736 uint8_t *d = dst_bytes; 4737 src_bytes += src_stride; 4738 dst_bytes += dst_stride; 4739 w = byte_width; 4740 4741 while (w >= 2 && ((uintptr_t)d & 3)) 4742 { 4743 *(uint16_t *)d = *(uint16_t *)s; 4744 w -= 2; 4745 s += 2; 4746 d += 2; 4747 } 4748 4749 while (w >= 4 && ((uintptr_t)d & 15)) 4750 { 4751 *(uint32_t *)d = *(uint32_t *)s; 4752 4753 w -= 4; 4754 s += 4; 4755 d += 4; 4756 } 4757 4758 while (w >= 64) 4759 { 4760 __m128i xmm0, xmm1, xmm2, xmm3; 4761 4762 xmm0 = load_128_unaligned ((__m128i*)(s)); 4763 xmm1 = load_128_unaligned ((__m128i*)(s + 16)); 4764 xmm2 = load_128_unaligned ((__m128i*)(s + 32)); 4765 xmm3 = load_128_unaligned ((__m128i*)(s + 48)); 4766 4767 save_128_aligned ((__m128i*)(d), xmm0); 4768 save_128_aligned ((__m128i*)(d + 16), xmm1); 4769 save_128_aligned ((__m128i*)(d + 32), xmm2); 4770 save_128_aligned ((__m128i*)(d + 48), xmm3); 4771 4772 s += 64; 4773 d += 64; 4774 w -= 64; 4775 } 4776 4777 while (w >= 16) 4778 { 4779 save_128_aligned ((__m128i*)d, load_128_unaligned ((__m128i*)s) ); 4780 4781 w -= 16; 4782 d += 16; 4783 s += 16; 4784 } 4785 4786 while (w >= 4) 4787 { 4788 *(uint32_t *)d = *(uint32_t *)s; 4789 4790 w -= 4; 4791 s += 4; 4792 d += 4; 4793 } 4794 4795 if (w >= 2) 4796 { 4797 *(uint16_t *)d = *(uint16_t *)s; 4798 w -= 2; 4799 s += 2; 4800 d += 2; 4801 } 4802 } 4803 4804 return TRUE; 4805 } 4806 4807 static void 4808 sse2_composite_copy_area (pixman_implementation_t *imp, 4809 pixman_composite_info_t *info) 4810 { 4811 PIXMAN_COMPOSITE_ARGS (info); 4812 sse2_blt (imp, src_image->bits.bits, 4813 dest_image->bits.bits, 4814 src_image->bits.rowstride, 4815 dest_image->bits.rowstride, 4816 PIXMAN_FORMAT_BPP (src_image->bits.format), 4817 PIXMAN_FORMAT_BPP (dest_image->bits.format), 4818 src_x, src_y, dest_x, dest_y, width, height); 4819 } 4820 4821 static void 4822 sse2_composite_over_x888_8_8888 (pixman_implementation_t *imp, 4823 pixman_composite_info_t *info) 4824 { 4825 PIXMAN_COMPOSITE_ARGS (info); 4826 uint32_t *src, *src_line, s; 4827 uint32_t *dst, *dst_line, d; 4828 uint8_t *mask, *mask_line; 4829 uint32_t m; 4830 int src_stride, mask_stride, dst_stride; 4831 int32_t w; 4832 __m128i ms; 4833 4834 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 4835 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 4836 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 4837 4838 PIXMAN_IMAGE_GET_LINE ( 4839 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 4840 PIXMAN_IMAGE_GET_LINE ( 4841 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 4842 PIXMAN_IMAGE_GET_LINE ( 4843 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 4844 4845 while (height--) 4846 { 4847 src = src_line; 4848 src_line += src_stride; 4849 dst = dst_line; 4850 dst_line += dst_stride; 4851 mask = mask_line; 4852 mask_line += mask_stride; 4853 4854 w = width; 4855 4856 while (w && (uintptr_t)dst & 15) 4857 { 4858 s = 0xff000000 | *src++; 4859 m = (uint32_t) *mask++; 4860 d = *dst; 4861 ms = unpack_32_1x128 (s); 4862 4863 if (m != 0xff) 4864 { 4865 __m128i ma = expand_alpha_rev_1x128 (unpack_32_1x128 (m)); 4866 __m128i md = unpack_32_1x128 (d); 4867 4868 ms = in_over_1x128 (&ms, &mask_00ff, &ma, &md); 4869 } 4870 4871 *dst++ = pack_1x128_32 (ms); 4872 w--; 4873 } 4874 4875 while (w >= 4) 4876 { 4877 m = *(uint32_t*) mask; 4878 xmm_src = _mm_or_si128 ( 4879 load_128_unaligned ((__m128i*)src), mask_ff000000); 4880 4881 if (m == 0xffffffff) 4882 { 4883 save_128_aligned ((__m128i*)dst, xmm_src); 4884 } 4885 else 4886 { 4887 xmm_dst = load_128_aligned ((__m128i*)dst); 4888 4889 xmm_mask = _mm_unpacklo_epi16 (unpack_32_1x128 (m), _mm_setzero_si128()); 4890 4891 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 4892 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 4893 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 4894 4895 expand_alpha_rev_2x128 ( 4896 xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 4897 4898 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, 4899 &mask_00ff, &mask_00ff, &xmm_mask_lo, &xmm_mask_hi, 4900 &xmm_dst_lo, &xmm_dst_hi); 4901 4902 save_128_aligned ((__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 4903 } 4904 4905 src += 4; 4906 dst += 4; 4907 mask += 4; 4908 w -= 4; 4909 } 4910 4911 while (w) 4912 { 4913 m = (uint32_t) *mask++; 4914 4915 if (m) 4916 { 4917 s = 0xff000000 | *src; 4918 4919 if (m == 0xff) 4920 { 4921 *dst = s; 4922 } 4923 else 4924 { 4925 __m128i ma, md, ms; 4926 4927 d = *dst; 4928 4929 ma = expand_alpha_rev_1x128 (unpack_32_1x128 (m)); 4930 md = unpack_32_1x128 (d); 4931 ms = unpack_32_1x128 (s); 4932 4933 *dst = pack_1x128_32 (in_over_1x128 (&ms, &mask_00ff, &ma, &md)); 4934 } 4935 4936 } 4937 4938 src++; 4939 dst++; 4940 w--; 4941 } 4942 } 4943 4944 } 4945 4946 static void 4947 sse2_composite_over_8888_8_8888 (pixman_implementation_t *imp, 4948 pixman_composite_info_t *info) 4949 { 4950 PIXMAN_COMPOSITE_ARGS (info); 4951 uint32_t *src, *src_line, s; 4952 uint32_t *dst, *dst_line, d; 4953 uint8_t *mask, *mask_line; 4954 uint32_t m; 4955 int src_stride, mask_stride, dst_stride; 4956 int32_t w; 4957 4958 __m128i xmm_src, xmm_src_lo, xmm_src_hi, xmm_srca_lo, xmm_srca_hi; 4959 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 4960 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 4961 4962 PIXMAN_IMAGE_GET_LINE ( 4963 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 4964 PIXMAN_IMAGE_GET_LINE ( 4965 mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); 4966 PIXMAN_IMAGE_GET_LINE ( 4967 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 4968 4969 while (height--) 4970 { 4971 src = src_line; 4972 src_line += src_stride; 4973 dst = dst_line; 4974 dst_line += dst_stride; 4975 mask = mask_line; 4976 mask_line += mask_stride; 4977 4978 w = width; 4979 4980 while (w && (uintptr_t)dst & 15) 4981 { 4982 uint32_t sa; 4983 4984 s = *src++; 4985 m = (uint32_t) *mask++; 4986 d = *dst; 4987 4988 sa = s >> 24; 4989 4990 if (m) 4991 { 4992 if (sa == 0xff && m == 0xff) 4993 { 4994 *dst = s; 4995 } 4996 else 4997 { 4998 __m128i ms, md, ma, msa; 4999 5000 ma = expand_alpha_rev_1x128 (load_32_1x128 (m)); 5001 ms = unpack_32_1x128 (s); 5002 md = unpack_32_1x128 (d); 5003 5004 msa = expand_alpha_rev_1x128 (load_32_1x128 (sa)); 5005 5006 *dst = pack_1x128_32 (in_over_1x128 (&ms, &msa, &ma, &md)); 5007 } 5008 } 5009 5010 dst++; 5011 w--; 5012 } 5013 5014 while (w >= 4) 5015 { 5016 m = *(uint32_t *) mask; 5017 5018 if (m) 5019 { 5020 xmm_src = load_128_unaligned ((__m128i*)src); 5021 5022 if (m == 0xffffffff && is_opaque (xmm_src)) 5023 { 5024 save_128_aligned ((__m128i *)dst, xmm_src); 5025 } 5026 else 5027 { 5028 xmm_dst = load_128_aligned ((__m128i *)dst); 5029 5030 xmm_mask = _mm_unpacklo_epi16 (unpack_32_1x128 (m), _mm_setzero_si128()); 5031 5032 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 5033 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 5034 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 5035 5036 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi); 5037 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 5038 5039 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi, 5040 &xmm_mask_lo, &xmm_mask_hi, &xmm_dst_lo, &xmm_dst_hi); 5041 5042 save_128_aligned ((__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 5043 } 5044 } 5045 5046 src += 4; 5047 dst += 4; 5048 mask += 4; 5049 w -= 4; 5050 } 5051 5052 while (w) 5053 { 5054 uint32_t sa; 5055 5056 s = *src++; 5057 m = (uint32_t) *mask++; 5058 d = *dst; 5059 5060 sa = s >> 24; 5061 5062 if (m) 5063 { 5064 if (sa == 0xff && m == 0xff) 5065 { 5066 *dst = s; 5067 } 5068 else 5069 { 5070 __m128i ms, md, ma, msa; 5071 5072 ma = expand_alpha_rev_1x128 (load_32_1x128 (m)); 5073 ms = unpack_32_1x128 (s); 5074 md = unpack_32_1x128 (d); 5075 5076 msa = expand_alpha_rev_1x128 (load_32_1x128 (sa)); 5077 5078 *dst = pack_1x128_32 (in_over_1x128 (&ms, &msa, &ma, &md)); 5079 } 5080 } 5081 5082 dst++; 5083 w--; 5084 } 5085 } 5086 5087 } 5088 5089 static void 5090 sse2_composite_over_reverse_n_8888 (pixman_implementation_t *imp, 5091 pixman_composite_info_t *info) 5092 { 5093 PIXMAN_COMPOSITE_ARGS (info); 5094 uint32_t src; 5095 uint32_t *dst_line, *dst; 5096 __m128i xmm_src; 5097 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 5098 __m128i xmm_dsta_hi, xmm_dsta_lo; 5099 int dst_stride; 5100 int32_t w; 5101 5102 src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); 5103 5104 if (src == 0) 5105 return; 5106 5107 PIXMAN_IMAGE_GET_LINE ( 5108 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 5109 5110 xmm_src = expand_pixel_32_1x128 (src); 5111 5112 while (height--) 5113 { 5114 dst = dst_line; 5115 5116 dst_line += dst_stride; 5117 w = width; 5118 5119 while (w && (uintptr_t)dst & 15) 5120 { 5121 __m128i vd; 5122 5123 vd = unpack_32_1x128 (*dst); 5124 5125 *dst = pack_1x128_32 (over_1x128 (vd, expand_alpha_1x128 (vd), 5126 xmm_src)); 5127 w--; 5128 dst++; 5129 } 5130 5131 while (w >= 4) 5132 { 5133 __m128i tmp_lo, tmp_hi; 5134 5135 xmm_dst = load_128_aligned ((__m128i*)dst); 5136 5137 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 5138 expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, &xmm_dsta_lo, &xmm_dsta_hi); 5139 5140 tmp_lo = xmm_src; 5141 tmp_hi = xmm_src; 5142 5143 over_2x128 (&xmm_dst_lo, &xmm_dst_hi, 5144 &xmm_dsta_lo, &xmm_dsta_hi, 5145 &tmp_lo, &tmp_hi); 5146 5147 save_128_aligned ( 5148 (__m128i*)dst, pack_2x128_128 (tmp_lo, tmp_hi)); 5149 5150 w -= 4; 5151 dst += 4; 5152 } 5153 5154 while (w) 5155 { 5156 __m128i vd; 5157 5158 vd = unpack_32_1x128 (*dst); 5159 5160 *dst = pack_1x128_32 (over_1x128 (vd, expand_alpha_1x128 (vd), 5161 xmm_src)); 5162 w--; 5163 dst++; 5164 } 5165 5166 } 5167 5168 } 5169 5170 static void 5171 sse2_composite_over_8888_8888_8888 (pixman_implementation_t *imp, 5172 pixman_composite_info_t *info) 5173 { 5174 PIXMAN_COMPOSITE_ARGS (info); 5175 uint32_t *src, *src_line, s; 5176 uint32_t *dst, *dst_line, d; 5177 uint32_t *mask, *mask_line; 5178 uint32_t m; 5179 int src_stride, mask_stride, dst_stride; 5180 int32_t w; 5181 5182 __m128i xmm_src, xmm_src_lo, xmm_src_hi, xmm_srca_lo, xmm_srca_hi; 5183 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 5184 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 5185 5186 PIXMAN_IMAGE_GET_LINE ( 5187 dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); 5188 PIXMAN_IMAGE_GET_LINE ( 5189 mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1); 5190 PIXMAN_IMAGE_GET_LINE ( 5191 src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); 5192 5193 while (height--) 5194 { 5195 src = src_line; 5196 src_line += src_stride; 5197 dst = dst_line; 5198 dst_line += dst_stride; 5199 mask = mask_line; 5200 mask_line += mask_stride; 5201 5202 w = width; 5203 5204 while (w && (uintptr_t)dst & 15) 5205 { 5206 uint32_t sa; 5207 5208 s = *src++; 5209 m = (*mask++) >> 24; 5210 d = *dst; 5211 5212 sa = s >> 24; 5213 5214 if (m) 5215 { 5216 if (sa == 0xff && m == 0xff) 5217 { 5218 *dst = s; 5219 } 5220 else 5221 { 5222 __m128i ms, md, ma, msa; 5223 5224 ma = expand_alpha_rev_1x128 (load_32_1x128 (m)); 5225 ms = unpack_32_1x128 (s); 5226 md = unpack_32_1x128 (d); 5227 5228 msa = expand_alpha_rev_1x128 (load_32_1x128 (sa)); 5229 5230 *dst = pack_1x128_32 (in_over_1x128 (&ms, &msa, &ma, &md)); 5231 } 5232 } 5233 5234 dst++; 5235 w--; 5236 } 5237 5238 while (w >= 4) 5239 { 5240 xmm_mask = load_128_unaligned ((__m128i*)mask); 5241 5242 if (!is_transparent (xmm_mask)) 5243 { 5244 xmm_src = load_128_unaligned ((__m128i*)src); 5245 5246 if (is_opaque (xmm_mask) && is_opaque (xmm_src)) 5247 { 5248 save_128_aligned ((__m128i *)dst, xmm_src); 5249 } 5250 else 5251 { 5252 xmm_dst = load_128_aligned ((__m128i *)dst); 5253 5254 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 5255 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 5256 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 5257 5258 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi); 5259 expand_alpha_2x128 (xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 5260 5261 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi, 5262 &xmm_mask_lo, &xmm_mask_hi, &xmm_dst_lo, &xmm_dst_hi); 5263 5264 save_128_aligned ((__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 5265 } 5266 } 5267 5268 src += 4; 5269 dst += 4; 5270 mask += 4; 5271 w -= 4; 5272 } 5273 5274 while (w) 5275 { 5276 uint32_t sa; 5277 5278 s = *src++; 5279 m = (*mask++) >> 24; 5280 d = *dst; 5281 5282 sa = s >> 24; 5283 5284 if (m) 5285 { 5286 if (sa == 0xff && m == 0xff) 5287 { 5288 *dst = s; 5289 } 5290 else 5291 { 5292 __m128i ms, md, ma, msa; 5293 5294 ma = expand_alpha_rev_1x128 (load_32_1x128 (m)); 5295 ms = unpack_32_1x128 (s); 5296 md = unpack_32_1x128 (d); 5297 5298 msa = expand_alpha_rev_1x128 (load_32_1x128 (sa)); 5299 5300 *dst = pack_1x128_32 (in_over_1x128 (&ms, &msa, &ma, &md)); 5301 } 5302 } 5303 5304 dst++; 5305 w--; 5306 } 5307 } 5308 5309 } 5310 5311 /* A variant of 'sse2_combine_over_u' with minor tweaks */ 5312 static force_inline void 5313 scaled_nearest_scanline_sse2_8888_8888_OVER (uint32_t* pd, 5314 const uint32_t* ps, 5315 int32_t w, 5316 pixman_fixed_t vx, 5317 pixman_fixed_t unit_x, 5318 pixman_fixed_t src_width_fixed, 5319 pixman_bool_t fully_transparent_src) 5320 { 5321 uint32_t s, d; 5322 const uint32_t* pm = NULL; 5323 5324 __m128i xmm_dst_lo, xmm_dst_hi; 5325 __m128i xmm_src_lo, xmm_src_hi; 5326 __m128i xmm_alpha_lo, xmm_alpha_hi; 5327 5328 if (fully_transparent_src) 5329 return; 5330 5331 /* Align dst on a 16-byte boundary */ 5332 while (w && ((uintptr_t)pd & 15)) 5333 { 5334 d = *pd; 5335 s = combine1 (ps + pixman_fixed_to_int (vx), pm); 5336 vx += unit_x; 5337 while (vx >= 0) 5338 vx -= src_width_fixed; 5339 5340 *pd++ = core_combine_over_u_pixel_sse2 (s, d); 5341 if (pm) 5342 pm++; 5343 w--; 5344 } 5345 5346 while (w >= 4) 5347 { 5348 __m128i tmp; 5349 uint32_t tmp1, tmp2, tmp3, tmp4; 5350 5351 tmp1 = *(ps + pixman_fixed_to_int (vx)); 5352 vx += unit_x; 5353 while (vx >= 0) 5354 vx -= src_width_fixed; 5355 tmp2 = *(ps + pixman_fixed_to_int (vx)); 5356 vx += unit_x; 5357 while (vx >= 0) 5358 vx -= src_width_fixed; 5359 tmp3 = *(ps + pixman_fixed_to_int (vx)); 5360 vx += unit_x; 5361 while (vx >= 0) 5362 vx -= src_width_fixed; 5363 tmp4 = *(ps + pixman_fixed_to_int (vx)); 5364 vx += unit_x; 5365 while (vx >= 0) 5366 vx -= src_width_fixed; 5367 5368 tmp = _mm_set_epi32 (tmp4, tmp3, tmp2, tmp1); 5369 5370 xmm_src_hi = combine4 ((__m128i*)&tmp, (__m128i*)pm); 5371 5372 if (is_opaque (xmm_src_hi)) 5373 { 5374 save_128_aligned ((__m128i*)pd, xmm_src_hi); 5375 } 5376 else if (!is_zero (xmm_src_hi)) 5377 { 5378 xmm_dst_hi = load_128_aligned ((__m128i*) pd); 5379 5380 unpack_128_2x128 (xmm_src_hi, &xmm_src_lo, &xmm_src_hi); 5381 unpack_128_2x128 (xmm_dst_hi, &xmm_dst_lo, &xmm_dst_hi); 5382 5383 expand_alpha_2x128 ( 5384 xmm_src_lo, xmm_src_hi, &xmm_alpha_lo, &xmm_alpha_hi); 5385 5386 over_2x128 (&xmm_src_lo, &xmm_src_hi, 5387 &xmm_alpha_lo, &xmm_alpha_hi, 5388 &xmm_dst_lo, &xmm_dst_hi); 5389 5390 /* rebuid the 4 pixel data and save*/ 5391 save_128_aligned ((__m128i*)pd, 5392 pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 5393 } 5394 5395 w -= 4; 5396 pd += 4; 5397 if (pm) 5398 pm += 4; 5399 } 5400 5401 while (w) 5402 { 5403 d = *pd; 5404 s = combine1 (ps + pixman_fixed_to_int (vx), pm); 5405 vx += unit_x; 5406 while (vx >= 0) 5407 vx -= src_width_fixed; 5408 5409 *pd++ = core_combine_over_u_pixel_sse2 (s, d); 5410 if (pm) 5411 pm++; 5412 5413 w--; 5414 } 5415 } 5416 5417 FAST_NEAREST_MAINLOOP (sse2_8888_8888_cover_OVER, 5418 scaled_nearest_scanline_sse2_8888_8888_OVER, 5419 uint32_t, uint32_t, COVER) 5420 FAST_NEAREST_MAINLOOP (sse2_8888_8888_none_OVER, 5421 scaled_nearest_scanline_sse2_8888_8888_OVER, 5422 uint32_t, uint32_t, NONE) 5423 FAST_NEAREST_MAINLOOP (sse2_8888_8888_pad_OVER, 5424 scaled_nearest_scanline_sse2_8888_8888_OVER, 5425 uint32_t, uint32_t, PAD) 5426 FAST_NEAREST_MAINLOOP (sse2_8888_8888_normal_OVER, 5427 scaled_nearest_scanline_sse2_8888_8888_OVER, 5428 uint32_t, uint32_t, NORMAL) 5429 5430 static force_inline void 5431 scaled_nearest_scanline_sse2_8888_n_8888_OVER (const uint32_t * mask, 5432 uint32_t * dst, 5433 const uint32_t * src, 5434 int32_t w, 5435 pixman_fixed_t vx, 5436 pixman_fixed_t unit_x, 5437 pixman_fixed_t src_width_fixed, 5438 pixman_bool_t zero_src) 5439 { 5440 __m128i xmm_mask; 5441 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 5442 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 5443 __m128i xmm_alpha_lo, xmm_alpha_hi; 5444 5445 if (zero_src || (*mask >> 24) == 0) 5446 return; 5447 5448 xmm_mask = create_mask_16_128 (*mask >> 24); 5449 5450 while (w && (uintptr_t)dst & 15) 5451 { 5452 uint32_t s = *(src + pixman_fixed_to_int (vx)); 5453 vx += unit_x; 5454 while (vx >= 0) 5455 vx -= src_width_fixed; 5456 5457 if (s) 5458 { 5459 uint32_t d = *dst; 5460 5461 __m128i ms = unpack_32_1x128 (s); 5462 __m128i alpha = expand_alpha_1x128 (ms); 5463 __m128i dest = xmm_mask; 5464 __m128i alpha_dst = unpack_32_1x128 (d); 5465 5466 *dst = pack_1x128_32 ( 5467 in_over_1x128 (&ms, &alpha, &dest, &alpha_dst)); 5468 } 5469 dst++; 5470 w--; 5471 } 5472 5473 while (w >= 4) 5474 { 5475 uint32_t tmp1, tmp2, tmp3, tmp4; 5476 5477 tmp1 = *(src + pixman_fixed_to_int (vx)); 5478 vx += unit_x; 5479 while (vx >= 0) 5480 vx -= src_width_fixed; 5481 tmp2 = *(src + pixman_fixed_to_int (vx)); 5482 vx += unit_x; 5483 while (vx >= 0) 5484 vx -= src_width_fixed; 5485 tmp3 = *(src + pixman_fixed_to_int (vx)); 5486 vx += unit_x; 5487 while (vx >= 0) 5488 vx -= src_width_fixed; 5489 tmp4 = *(src + pixman_fixed_to_int (vx)); 5490 vx += unit_x; 5491 while (vx >= 0) 5492 vx -= src_width_fixed; 5493 5494 xmm_src = _mm_set_epi32 (tmp4, tmp3, tmp2, tmp1); 5495 5496 if (!is_zero (xmm_src)) 5497 { 5498 xmm_dst = load_128_aligned ((__m128i*)dst); 5499 5500 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 5501 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 5502 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 5503 &xmm_alpha_lo, &xmm_alpha_hi); 5504 5505 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, 5506 &xmm_alpha_lo, &xmm_alpha_hi, 5507 &xmm_mask, &xmm_mask, 5508 &xmm_dst_lo, &xmm_dst_hi); 5509 5510 save_128_aligned ( 5511 (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 5512 } 5513 5514 dst += 4; 5515 w -= 4; 5516 } 5517 5518 while (w) 5519 { 5520 uint32_t s = *(src + pixman_fixed_to_int (vx)); 5521 vx += unit_x; 5522 while (vx >= 0) 5523 vx -= src_width_fixed; 5524 5525 if (s) 5526 { 5527 uint32_t d = *dst; 5528 5529 __m128i ms = unpack_32_1x128 (s); 5530 __m128i alpha = expand_alpha_1x128 (ms); 5531 __m128i mask = xmm_mask; 5532 __m128i dest = unpack_32_1x128 (d); 5533 5534 *dst = pack_1x128_32 ( 5535 in_over_1x128 (&ms, &alpha, &mask, &dest)); 5536 } 5537 5538 dst++; 5539 w--; 5540 } 5541 5542 } 5543 5544 FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_cover_OVER, 5545 scaled_nearest_scanline_sse2_8888_n_8888_OVER, 5546 uint32_t, uint32_t, uint32_t, COVER, TRUE, TRUE) 5547 FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_pad_OVER, 5548 scaled_nearest_scanline_sse2_8888_n_8888_OVER, 5549 uint32_t, uint32_t, uint32_t, PAD, TRUE, TRUE) 5550 FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_none_OVER, 5551 scaled_nearest_scanline_sse2_8888_n_8888_OVER, 5552 uint32_t, uint32_t, uint32_t, NONE, TRUE, TRUE) 5553 FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER, 5554 scaled_nearest_scanline_sse2_8888_n_8888_OVER, 5555 uint32_t, uint32_t, uint32_t, NORMAL, TRUE, TRUE) 5556 5557 #if BILINEAR_INTERPOLATION_BITS < 8 5558 # define BILINEAR_DECLARE_VARIABLES \ 5559 const __m128i xmm_wt = _mm_set_epi16 (wt, wt, wt, wt, wt, wt, wt, wt); \ 5560 const __m128i xmm_wb = _mm_set_epi16 (wb, wb, wb, wb, wb, wb, wb, wb); \ 5561 const __m128i xmm_addc = _mm_set_epi16 (0, 1, 0, 1, 0, 1, 0, 1); \ 5562 const __m128i xmm_ux = _mm_set_epi16 (unit_x, -unit_x, unit_x, -unit_x, \ 5563 unit_x, -unit_x, unit_x, -unit_x); \ 5564 const __m128i xmm_zero = _mm_setzero_si128 (); \ 5565 __m128i xmm_x = _mm_set_epi16 (vx, -(vx + 1), vx, -(vx + 1), \ 5566 vx, -(vx + 1), vx, -(vx + 1)) 5567 #else 5568 # define BILINEAR_DECLARE_VARIABLES \ 5569 const __m128i xmm_wt = _mm_set_epi16 (wt, wt, wt, wt, wt, wt, wt, wt); \ 5570 const __m128i xmm_wb = _mm_set_epi16 (wb, wb, wb, wb, wb, wb, wb, wb); \ 5571 const __m128i xmm_addc = _mm_set_epi16 (0, 0, 0, 0, 1, 1, 1, 1); \ 5572 const __m128i xmm_ux = _mm_set_epi16 (unit_x, unit_x, unit_x, unit_x, \ 5573 -unit_x, -unit_x, -unit_x, -unit_x); \ 5574 const __m128i xmm_zero = _mm_setzero_si128 (); \ 5575 __m128i xmm_x = _mm_set_epi16 (vx, vx, vx, vx, \ 5576 -(vx + 1), -(vx + 1), -(vx + 1), -(vx + 1)) 5577 #endif 5578 5579 #define BILINEAR_INTERPOLATE_ONE_PIXEL(pix) \ 5580 do { \ 5581 __m128i xmm_wh, xmm_lo, xmm_hi, a; \ 5582 /* fetch 2x2 pixel block into sse2 registers */ \ 5583 __m128i tltr = _mm_loadl_epi64 ( \ 5584 (__m128i *)&src_top[pixman_fixed_to_int (vx)]); \ 5585 __m128i blbr = _mm_loadl_epi64 ( \ 5586 (__m128i *)&src_bottom[pixman_fixed_to_int (vx)]); \ 5587 vx += unit_x; \ 5588 /* vertical interpolation */ \ 5589 a = _mm_add_epi16 (_mm_mullo_epi16 (_mm_unpacklo_epi8 (tltr, xmm_zero), \ 5590 xmm_wt), \ 5591 _mm_mullo_epi16 (_mm_unpacklo_epi8 (blbr, xmm_zero), \ 5592 xmm_wb)); \ 5593 if (BILINEAR_INTERPOLATION_BITS < 8) \ 5594 { \ 5595 /* calculate horizontal weights */ \ 5596 xmm_wh = _mm_add_epi16 (xmm_addc, _mm_srli_epi16 (xmm_x, \ 5597 16 - BILINEAR_INTERPOLATION_BITS)); \ 5598 xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ 5599 /* horizontal interpolation */ \ 5600 a = _mm_madd_epi16 (_mm_unpackhi_epi16 (_mm_shuffle_epi32 ( \ 5601 a, _MM_SHUFFLE (1, 0, 3, 2)), a), xmm_wh); \ 5602 } \ 5603 else \ 5604 { \ 5605 /* calculate horizontal weights */ \ 5606 xmm_wh = _mm_add_epi16 (xmm_addc, _mm_srli_epi16 (xmm_x, \ 5607 16 - BILINEAR_INTERPOLATION_BITS)); \ 5608 xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ 5609 /* horizontal interpolation */ \ 5610 xmm_lo = _mm_mullo_epi16 (a, xmm_wh); \ 5611 xmm_hi = _mm_mulhi_epu16 (a, xmm_wh); \ 5612 a = _mm_add_epi32 (_mm_unpacklo_epi16 (xmm_lo, xmm_hi), \ 5613 _mm_unpackhi_epi16 (xmm_lo, xmm_hi)); \ 5614 } \ 5615 /* shift and pack the result */ \ 5616 a = _mm_srli_epi32 (a, BILINEAR_INTERPOLATION_BITS * 2); \ 5617 a = _mm_packs_epi32 (a, a); \ 5618 a = _mm_packus_epi16 (a, a); \ 5619 pix = _mm_cvtsi128_si32 (a); \ 5620 } while (0) 5621 5622 #define BILINEAR_SKIP_ONE_PIXEL() \ 5623 do { \ 5624 vx += unit_x; \ 5625 xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ 5626 } while(0) 5627 5628 static force_inline void 5629 scaled_bilinear_scanline_sse2_8888_8888_SRC (uint32_t * dst, 5630 const uint32_t * mask, 5631 const uint32_t * src_top, 5632 const uint32_t * src_bottom, 5633 int32_t w, 5634 int wt, 5635 int wb, 5636 pixman_fixed_t vx, 5637 pixman_fixed_t unit_x, 5638 pixman_fixed_t max_vx, 5639 pixman_bool_t zero_src) 5640 { 5641 BILINEAR_DECLARE_VARIABLES; 5642 uint32_t pix1, pix2, pix3, pix4; 5643 5644 while ((w -= 4) >= 0) 5645 { 5646 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5647 BILINEAR_INTERPOLATE_ONE_PIXEL (pix2); 5648 BILINEAR_INTERPOLATE_ONE_PIXEL (pix3); 5649 BILINEAR_INTERPOLATE_ONE_PIXEL (pix4); 5650 *dst++ = pix1; 5651 *dst++ = pix2; 5652 *dst++ = pix3; 5653 *dst++ = pix4; 5654 } 5655 5656 if (w & 2) 5657 { 5658 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5659 BILINEAR_INTERPOLATE_ONE_PIXEL (pix2); 5660 *dst++ = pix1; 5661 *dst++ = pix2; 5662 } 5663 5664 if (w & 1) 5665 { 5666 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5667 *dst = pix1; 5668 } 5669 5670 } 5671 5672 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_cover_SRC, 5673 scaled_bilinear_scanline_sse2_8888_8888_SRC, 5674 uint32_t, uint32_t, uint32_t, 5675 COVER, FLAG_NONE) 5676 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_pad_SRC, 5677 scaled_bilinear_scanline_sse2_8888_8888_SRC, 5678 uint32_t, uint32_t, uint32_t, 5679 PAD, FLAG_NONE) 5680 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_none_SRC, 5681 scaled_bilinear_scanline_sse2_8888_8888_SRC, 5682 uint32_t, uint32_t, uint32_t, 5683 NONE, FLAG_NONE) 5684 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_normal_SRC, 5685 scaled_bilinear_scanline_sse2_8888_8888_SRC, 5686 uint32_t, uint32_t, uint32_t, 5687 NORMAL, FLAG_NONE) 5688 5689 static force_inline void 5690 scaled_bilinear_scanline_sse2_8888_8888_OVER (uint32_t * dst, 5691 const uint32_t * mask, 5692 const uint32_t * src_top, 5693 const uint32_t * src_bottom, 5694 int32_t w, 5695 int wt, 5696 int wb, 5697 pixman_fixed_t vx, 5698 pixman_fixed_t unit_x, 5699 pixman_fixed_t max_vx, 5700 pixman_bool_t zero_src) 5701 { 5702 BILINEAR_DECLARE_VARIABLES; 5703 uint32_t pix1, pix2, pix3, pix4; 5704 5705 while (w && ((uintptr_t)dst & 15)) 5706 { 5707 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5708 5709 if (pix1) 5710 { 5711 pix2 = *dst; 5712 *dst = core_combine_over_u_pixel_sse2 (pix1, pix2); 5713 } 5714 5715 w--; 5716 dst++; 5717 } 5718 5719 while (w >= 4) 5720 { 5721 __m128i xmm_src; 5722 __m128i xmm_src_hi, xmm_src_lo, xmm_dst_hi, xmm_dst_lo; 5723 __m128i xmm_alpha_hi, xmm_alpha_lo; 5724 5725 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5726 BILINEAR_INTERPOLATE_ONE_PIXEL (pix2); 5727 BILINEAR_INTERPOLATE_ONE_PIXEL (pix3); 5728 BILINEAR_INTERPOLATE_ONE_PIXEL (pix4); 5729 5730 xmm_src = _mm_set_epi32 (pix4, pix3, pix2, pix1); 5731 5732 if (!is_zero (xmm_src)) 5733 { 5734 if (is_opaque (xmm_src)) 5735 { 5736 save_128_aligned ((__m128i *)dst, xmm_src); 5737 } 5738 else 5739 { 5740 __m128i xmm_dst = load_128_aligned ((__m128i *)dst); 5741 5742 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 5743 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 5744 5745 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_alpha_lo, &xmm_alpha_hi); 5746 over_2x128 (&xmm_src_lo, &xmm_src_hi, &xmm_alpha_lo, &xmm_alpha_hi, 5747 &xmm_dst_lo, &xmm_dst_hi); 5748 5749 save_128_aligned ((__m128i *)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 5750 } 5751 } 5752 5753 w -= 4; 5754 dst += 4; 5755 } 5756 5757 while (w) 5758 { 5759 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5760 5761 if (pix1) 5762 { 5763 pix2 = *dst; 5764 *dst = core_combine_over_u_pixel_sse2 (pix1, pix2); 5765 } 5766 5767 w--; 5768 dst++; 5769 } 5770 } 5771 5772 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_cover_OVER, 5773 scaled_bilinear_scanline_sse2_8888_8888_OVER, 5774 uint32_t, uint32_t, uint32_t, 5775 COVER, FLAG_NONE) 5776 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_pad_OVER, 5777 scaled_bilinear_scanline_sse2_8888_8888_OVER, 5778 uint32_t, uint32_t, uint32_t, 5779 PAD, FLAG_NONE) 5780 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_none_OVER, 5781 scaled_bilinear_scanline_sse2_8888_8888_OVER, 5782 uint32_t, uint32_t, uint32_t, 5783 NONE, FLAG_NONE) 5784 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_normal_OVER, 5785 scaled_bilinear_scanline_sse2_8888_8888_OVER, 5786 uint32_t, uint32_t, uint32_t, 5787 NORMAL, FLAG_NONE) 5788 5789 static force_inline void 5790 scaled_bilinear_scanline_sse2_8888_8_8888_OVER (uint32_t * dst, 5791 const uint8_t * mask, 5792 const uint32_t * src_top, 5793 const uint32_t * src_bottom, 5794 int32_t w, 5795 int wt, 5796 int wb, 5797 pixman_fixed_t vx, 5798 pixman_fixed_t unit_x, 5799 pixman_fixed_t max_vx, 5800 pixman_bool_t zero_src) 5801 { 5802 BILINEAR_DECLARE_VARIABLES; 5803 uint32_t pix1, pix2, pix3, pix4; 5804 uint32_t m; 5805 5806 while (w && ((uintptr_t)dst & 15)) 5807 { 5808 uint32_t sa; 5809 5810 m = (uint32_t) *mask++; 5811 5812 if (m) 5813 { 5814 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5815 sa = pix1 >> 24; 5816 5817 if (sa == 0xff && m == 0xff) 5818 { 5819 *dst = pix1; 5820 } 5821 else 5822 { 5823 __m128i ms, md, ma, msa; 5824 5825 pix2 = *dst; 5826 ma = expand_alpha_rev_1x128 (load_32_1x128 (m)); 5827 ms = unpack_32_1x128 (pix1); 5828 md = unpack_32_1x128 (pix2); 5829 5830 msa = expand_alpha_rev_1x128 (load_32_1x128 (sa)); 5831 5832 *dst = pack_1x128_32 (in_over_1x128 (&ms, &msa, &ma, &md)); 5833 } 5834 } 5835 else 5836 { 5837 BILINEAR_SKIP_ONE_PIXEL (); 5838 } 5839 5840 w--; 5841 dst++; 5842 } 5843 5844 while (w >= 4) 5845 { 5846 __m128i xmm_src, xmm_src_lo, xmm_src_hi, xmm_srca_lo, xmm_srca_hi; 5847 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 5848 __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; 5849 5850 m = *(uint32_t*)mask; 5851 5852 if (m) 5853 { 5854 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5855 BILINEAR_INTERPOLATE_ONE_PIXEL (pix2); 5856 BILINEAR_INTERPOLATE_ONE_PIXEL (pix3); 5857 BILINEAR_INTERPOLATE_ONE_PIXEL (pix4); 5858 5859 xmm_src = _mm_set_epi32 (pix4, pix3, pix2, pix1); 5860 5861 if (m == 0xffffffff && is_opaque (xmm_src)) 5862 { 5863 save_128_aligned ((__m128i *)dst, xmm_src); 5864 } 5865 else 5866 { 5867 xmm_dst = load_128_aligned ((__m128i *)dst); 5868 5869 xmm_mask = _mm_unpacklo_epi16 (unpack_32_1x128 (m), _mm_setzero_si128()); 5870 5871 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 5872 unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); 5873 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 5874 5875 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi); 5876 expand_alpha_rev_2x128 (xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); 5877 5878 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi, 5879 &xmm_mask_lo, &xmm_mask_hi, &xmm_dst_lo, &xmm_dst_hi); 5880 5881 save_128_aligned ((__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 5882 } 5883 } 5884 else 5885 { 5886 BILINEAR_SKIP_ONE_PIXEL (); 5887 BILINEAR_SKIP_ONE_PIXEL (); 5888 BILINEAR_SKIP_ONE_PIXEL (); 5889 BILINEAR_SKIP_ONE_PIXEL (); 5890 } 5891 5892 w -= 4; 5893 dst += 4; 5894 mask += 4; 5895 } 5896 5897 while (w) 5898 { 5899 uint32_t sa; 5900 5901 m = (uint32_t) *mask++; 5902 5903 if (m) 5904 { 5905 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5906 sa = pix1 >> 24; 5907 5908 if (sa == 0xff && m == 0xff) 5909 { 5910 *dst = pix1; 5911 } 5912 else 5913 { 5914 __m128i ms, md, ma, msa; 5915 5916 pix2 = *dst; 5917 ma = expand_alpha_rev_1x128 (load_32_1x128 (m)); 5918 ms = unpack_32_1x128 (pix1); 5919 md = unpack_32_1x128 (pix2); 5920 5921 msa = expand_alpha_rev_1x128 (load_32_1x128 (sa)); 5922 5923 *dst = pack_1x128_32 (in_over_1x128 (&ms, &msa, &ma, &md)); 5924 } 5925 } 5926 else 5927 { 5928 BILINEAR_SKIP_ONE_PIXEL (); 5929 } 5930 5931 w--; 5932 dst++; 5933 } 5934 } 5935 5936 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8_8888_cover_OVER, 5937 scaled_bilinear_scanline_sse2_8888_8_8888_OVER, 5938 uint32_t, uint8_t, uint32_t, 5939 COVER, FLAG_HAVE_NON_SOLID_MASK) 5940 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8_8888_pad_OVER, 5941 scaled_bilinear_scanline_sse2_8888_8_8888_OVER, 5942 uint32_t, uint8_t, uint32_t, 5943 PAD, FLAG_HAVE_NON_SOLID_MASK) 5944 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8_8888_none_OVER, 5945 scaled_bilinear_scanline_sse2_8888_8_8888_OVER, 5946 uint32_t, uint8_t, uint32_t, 5947 NONE, FLAG_HAVE_NON_SOLID_MASK) 5948 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8_8888_normal_OVER, 5949 scaled_bilinear_scanline_sse2_8888_8_8888_OVER, 5950 uint32_t, uint8_t, uint32_t, 5951 NORMAL, FLAG_HAVE_NON_SOLID_MASK) 5952 5953 static force_inline void 5954 scaled_bilinear_scanline_sse2_8888_n_8888_OVER (uint32_t * dst, 5955 const uint32_t * mask, 5956 const uint32_t * src_top, 5957 const uint32_t * src_bottom, 5958 int32_t w, 5959 int wt, 5960 int wb, 5961 pixman_fixed_t vx, 5962 pixman_fixed_t unit_x, 5963 pixman_fixed_t max_vx, 5964 pixman_bool_t zero_src) 5965 { 5966 BILINEAR_DECLARE_VARIABLES; 5967 uint32_t pix1, pix2, pix3, pix4; 5968 __m128i xmm_mask; 5969 5970 if (zero_src || (*mask >> 24) == 0) 5971 return; 5972 5973 xmm_mask = create_mask_16_128 (*mask >> 24); 5974 5975 while (w && ((uintptr_t)dst & 15)) 5976 { 5977 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5978 if (pix1) 5979 { 5980 uint32_t d = *dst; 5981 5982 __m128i ms = unpack_32_1x128 (pix1); 5983 __m128i alpha = expand_alpha_1x128 (ms); 5984 __m128i dest = xmm_mask; 5985 __m128i alpha_dst = unpack_32_1x128 (d); 5986 5987 *dst = pack_1x128_32 5988 (in_over_1x128 (&ms, &alpha, &dest, &alpha_dst)); 5989 } 5990 5991 dst++; 5992 w--; 5993 } 5994 5995 while (w >= 4) 5996 { 5997 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 5998 BILINEAR_INTERPOLATE_ONE_PIXEL (pix2); 5999 BILINEAR_INTERPOLATE_ONE_PIXEL (pix3); 6000 BILINEAR_INTERPOLATE_ONE_PIXEL (pix4); 6001 6002 if (pix1 | pix2 | pix3 | pix4) 6003 { 6004 __m128i xmm_src, xmm_src_lo, xmm_src_hi; 6005 __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; 6006 __m128i xmm_alpha_lo, xmm_alpha_hi; 6007 6008 xmm_src = _mm_set_epi32 (pix4, pix3, pix2, pix1); 6009 6010 xmm_dst = load_128_aligned ((__m128i*)dst); 6011 6012 unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); 6013 unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); 6014 expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, 6015 &xmm_alpha_lo, &xmm_alpha_hi); 6016 6017 in_over_2x128 (&xmm_src_lo, &xmm_src_hi, 6018 &xmm_alpha_lo, &xmm_alpha_hi, 6019 &xmm_mask, &xmm_mask, 6020 &xmm_dst_lo, &xmm_dst_hi); 6021 6022 save_128_aligned 6023 ((__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); 6024 } 6025 6026 dst += 4; 6027 w -= 4; 6028 } 6029 6030 while (w) 6031 { 6032 BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); 6033 if (pix1) 6034 { 6035 uint32_t d = *dst; 6036 6037 __m128i ms = unpack_32_1x128 (pix1); 6038 __m128i alpha = expand_alpha_1x128 (ms); 6039 __m128i dest = xmm_mask; 6040 __m128i alpha_dst = unpack_32_1x128 (d); 6041 6042 *dst = pack_1x128_32 6043 (in_over_1x128 (&ms, &alpha, &dest, &alpha_dst)); 6044 } 6045 6046 dst++; 6047 w--; 6048 } 6049 } 6050 6051 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_n_8888_cover_OVER, 6052 scaled_bilinear_scanline_sse2_8888_n_8888_OVER, 6053 uint32_t, uint32_t, uint32_t, 6054 COVER, FLAG_HAVE_SOLID_MASK) 6055 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_n_8888_pad_OVER, 6056 scaled_bilinear_scanline_sse2_8888_n_8888_OVER, 6057 uint32_t, uint32_t, uint32_t, 6058 PAD, FLAG_HAVE_SOLID_MASK) 6059 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_n_8888_none_OVER, 6060 scaled_bilinear_scanline_sse2_8888_n_8888_OVER, 6061 uint32_t, uint32_t, uint32_t, 6062 NONE, FLAG_HAVE_SOLID_MASK) 6063 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER, 6064 scaled_bilinear_scanline_sse2_8888_n_8888_OVER, 6065 uint32_t, uint32_t, uint32_t, 6066 NORMAL, FLAG_HAVE_SOLID_MASK) 6067 6068 static const pixman_fast_path_t sse2_fast_paths[] = 6069 { 6070 /* PIXMAN_OP_OVER */ 6071 PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, sse2_composite_over_n_8_0565), 6072 PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, sse2_composite_over_n_8_0565), 6073 PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, sse2_composite_over_n_8888), 6074 PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, sse2_composite_over_n_8888), 6075 PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, sse2_composite_over_n_0565), 6076 PIXMAN_STD_FAST_PATH (OVER, solid, null, b5g6r5, sse2_composite_over_n_0565), 6077 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, sse2_composite_over_8888_8888), 6078 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, sse2_composite_over_8888_8888), 6079 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, sse2_composite_over_8888_8888), 6080 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, sse2_composite_over_8888_8888), 6081 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, sse2_composite_over_8888_0565), 6082 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, sse2_composite_over_8888_0565), 6083 PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, sse2_composite_over_n_8_8888), 6084 PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, sse2_composite_over_n_8_8888), 6085 PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, sse2_composite_over_n_8_8888), 6086 PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, sse2_composite_over_n_8_8888), 6087 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, sse2_composite_over_8888_8888_8888), 6088 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, sse2_composite_over_8888_8_8888), 6089 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, sse2_composite_over_8888_8_8888), 6090 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, sse2_composite_over_8888_8_8888), 6091 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, sse2_composite_over_8888_8_8888), 6092 PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, sse2_composite_over_x888_8_8888), 6093 PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, sse2_composite_over_x888_8_8888), 6094 PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, sse2_composite_over_x888_8_8888), 6095 PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, sse2_composite_over_x888_8_8888), 6096 PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, solid, a8r8g8b8, sse2_composite_over_x888_n_8888), 6097 PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, solid, x8r8g8b8, sse2_composite_over_x888_n_8888), 6098 PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, solid, a8b8g8r8, sse2_composite_over_x888_n_8888), 6099 PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, solid, x8b8g8r8, sse2_composite_over_x888_n_8888), 6100 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, sse2_composite_over_8888_n_8888), 6101 PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, sse2_composite_over_8888_n_8888), 6102 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, sse2_composite_over_8888_n_8888), 6103 PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, sse2_composite_over_8888_n_8888), 6104 PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, sse2_composite_over_n_8888_8888_ca), 6105 PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, sse2_composite_over_n_8888_8888_ca), 6106 PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, sse2_composite_over_n_8888_8888_ca), 6107 PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, sse2_composite_over_n_8888_8888_ca), 6108 PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, sse2_composite_over_n_8888_0565_ca), 6109 PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, sse2_composite_over_n_8888_0565_ca), 6110 PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, a8r8g8b8, sse2_composite_over_pixbuf_8888), 6111 PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, x8r8g8b8, sse2_composite_over_pixbuf_8888), 6112 PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, a8b8g8r8, sse2_composite_over_pixbuf_8888), 6113 PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, x8b8g8r8, sse2_composite_over_pixbuf_8888), 6114 PIXMAN_STD_FAST_PATH (OVER, pixbuf, pixbuf, r5g6b5, sse2_composite_over_pixbuf_0565), 6115 PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, b5g6r5, sse2_composite_over_pixbuf_0565), 6116 PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), 6117 PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), 6118 6119 /* PIXMAN_OP_OVER_REVERSE */ 6120 PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, sse2_composite_over_reverse_n_8888), 6121 PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, sse2_composite_over_reverse_n_8888), 6122 6123 /* PIXMAN_OP_ADD */ 6124 PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, sse2_composite_add_n_8888_8888_ca), 6125 PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, sse2_composite_add_8_8), 6126 PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, sse2_composite_add_8888_8888), 6127 PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, sse2_composite_add_8888_8888), 6128 PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, sse2_composite_add_n_8_8), 6129 PIXMAN_STD_FAST_PATH (ADD, solid, null, a8, sse2_composite_add_n_8), 6130 PIXMAN_STD_FAST_PATH (ADD, solid, null, x8r8g8b8, sse2_composite_add_n_8888), 6131 PIXMAN_STD_FAST_PATH (ADD, solid, null, a8r8g8b8, sse2_composite_add_n_8888), 6132 PIXMAN_STD_FAST_PATH (ADD, solid, null, x8b8g8r8, sse2_composite_add_n_8888), 6133 PIXMAN_STD_FAST_PATH (ADD, solid, null, a8b8g8r8, sse2_composite_add_n_8888), 6134 PIXMAN_STD_FAST_PATH (ADD, solid, a8, x8r8g8b8, sse2_composite_add_n_8_8888), 6135 PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, sse2_composite_add_n_8_8888), 6136 PIXMAN_STD_FAST_PATH (ADD, solid, a8, x8b8g8r8, sse2_composite_add_n_8_8888), 6137 PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, sse2_composite_add_n_8_8888), 6138 6139 /* PIXMAN_OP_SRC */ 6140 PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, sse2_composite_src_n_8_8888), 6141 PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, sse2_composite_src_n_8_8888), 6142 PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, sse2_composite_src_n_8_8888), 6143 PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, sse2_composite_src_n_8_8888), 6144 PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, sse2_composite_src_x888_0565), 6145 PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, sse2_composite_src_x888_0565), 6146 PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, sse2_composite_src_x888_0565), 6147 PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, sse2_composite_src_x888_0565), 6148 PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, sse2_composite_src_x888_8888), 6149 PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, sse2_composite_src_x888_8888), 6150 PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, sse2_composite_copy_area), 6151 PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, sse2_composite_copy_area), 6152 PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), 6153 PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), 6154 PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), 6155 PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), 6156 PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, sse2_composite_copy_area), 6157 PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, sse2_composite_copy_area), 6158 6159 /* PIXMAN_OP_IN */ 6160 PIXMAN_STD_FAST_PATH (IN, a8, null, a8, sse2_composite_in_8_8), 6161 PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, sse2_composite_in_n_8_8), 6162 PIXMAN_STD_FAST_PATH (IN, solid, null, a8, sse2_composite_in_n_8), 6163 6164 SIMPLE_NEAREST_FAST_PATH_COVER (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), 6165 SIMPLE_NEAREST_FAST_PATH_COVER (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), 6166 SIMPLE_NEAREST_FAST_PATH_COVER (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888), 6167 SIMPLE_NEAREST_FAST_PATH_COVER (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888), 6168 SIMPLE_NEAREST_FAST_PATH_NONE (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), 6169 SIMPLE_NEAREST_FAST_PATH_NONE (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), 6170 SIMPLE_NEAREST_FAST_PATH_NONE (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888), 6171 SIMPLE_NEAREST_FAST_PATH_NONE (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888), 6172 SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), 6173 SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), 6174 SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888), 6175 SIMPLE_NEAREST_FAST_PATH_PAD (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888), 6176 SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), 6177 SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), 6178 SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888), 6179 SIMPLE_NEAREST_FAST_PATH_NORMAL (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888), 6180 6181 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_n_8888), 6182 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_n_8888), 6183 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_n_8888), 6184 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_n_8888), 6185 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_n_8888), 6186 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_n_8888), 6187 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_n_8888), 6188 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_n_8888), 6189 6190 SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, sse2_8888_8888), 6191 SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, sse2_8888_8888), 6192 SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, sse2_8888_8888), 6193 SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, sse2_8888_8888), 6194 SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, sse2_8888_8888), 6195 SIMPLE_BILINEAR_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, sse2_8888_8888), 6196 6197 SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), 6198 SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), 6199 SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8888), 6200 SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8888), 6201 6202 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_n_8888), 6203 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_n_8888), 6204 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_n_8888), 6205 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_n_8888), 6206 6207 SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8_8888), 6208 SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8_8888), 6209 SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, sse2_8888_8_8888), 6210 SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, sse2_8888_8_8888), 6211 6212 { PIXMAN_OP_NONE }, 6213 }; 6214 6215 static uint32_t * 6216 sse2_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask) 6217 { 6218 int w = iter->width; 6219 __m128i ff000000 = mask_ff000000; 6220 uint32_t *dst = iter->buffer; 6221 uint32_t *src = (uint32_t *)iter->bits; 6222 6223 iter->bits += iter->stride; 6224 6225 while (w && ((uintptr_t)dst) & 0x0f) 6226 { 6227 *dst++ = (*src++) | 0xff000000; 6228 w--; 6229 } 6230 6231 while (w >= 4) 6232 { 6233 save_128_aligned ( 6234 (__m128i *)dst, _mm_or_si128 ( 6235 load_128_unaligned ((__m128i *)src), ff000000)); 6236 6237 dst += 4; 6238 src += 4; 6239 w -= 4; 6240 } 6241 6242 while (w) 6243 { 6244 *dst++ = (*src++) | 0xff000000; 6245 w--; 6246 } 6247 6248 return iter->buffer; 6249 } 6250 6251 static uint32_t * 6252 sse2_fetch_r5g6b5 (pixman_iter_t *iter, const uint32_t *mask) 6253 { 6254 int w = iter->width; 6255 uint32_t *dst = iter->buffer; 6256 uint16_t *src = (uint16_t *)iter->bits; 6257 __m128i ff000000 = mask_ff000000; 6258 6259 iter->bits += iter->stride; 6260 6261 while (w && ((uintptr_t)dst) & 0x0f) 6262 { 6263 uint16_t s = *src++; 6264 6265 *dst++ = convert_0565_to_8888 (s); 6266 w--; 6267 } 6268 6269 while (w >= 8) 6270 { 6271 __m128i lo, hi, s; 6272 6273 s = _mm_loadu_si128 ((__m128i *)src); 6274 6275 lo = unpack_565_to_8888 (_mm_unpacklo_epi16 (s, _mm_setzero_si128 ())); 6276 hi = unpack_565_to_8888 (_mm_unpackhi_epi16 (s, _mm_setzero_si128 ())); 6277 6278 save_128_aligned ((__m128i *)(dst + 0), _mm_or_si128 (lo, ff000000)); 6279 save_128_aligned ((__m128i *)(dst + 4), _mm_or_si128 (hi, ff000000)); 6280 6281 dst += 8; 6282 src += 8; 6283 w -= 8; 6284 } 6285 6286 while (w) 6287 { 6288 uint16_t s = *src++; 6289 6290 *dst++ = convert_0565_to_8888 (s); 6291 w--; 6292 } 6293 6294 return iter->buffer; 6295 } 6296 6297 static uint32_t * 6298 sse2_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask) 6299 { 6300 int w = iter->width; 6301 uint32_t *dst = iter->buffer; 6302 uint8_t *src = iter->bits; 6303 __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6; 6304 6305 iter->bits += iter->stride; 6306 6307 while (w && (((uintptr_t)dst) & 15)) 6308 { 6309 *dst++ = *(src++) << 24; 6310 w--; 6311 } 6312 6313 while (w >= 16) 6314 { 6315 xmm0 = _mm_loadu_si128((__m128i *)src); 6316 6317 xmm1 = _mm_unpacklo_epi8 (_mm_setzero_si128(), xmm0); 6318 xmm2 = _mm_unpackhi_epi8 (_mm_setzero_si128(), xmm0); 6319 xmm3 = _mm_unpacklo_epi16 (_mm_setzero_si128(), xmm1); 6320 xmm4 = _mm_unpackhi_epi16 (_mm_setzero_si128(), xmm1); 6321 xmm5 = _mm_unpacklo_epi16 (_mm_setzero_si128(), xmm2); 6322 xmm6 = _mm_unpackhi_epi16 (_mm_setzero_si128(), xmm2); 6323 6324 _mm_store_si128(((__m128i *)(dst + 0)), xmm3); 6325 _mm_store_si128(((__m128i *)(dst + 4)), xmm4); 6326 _mm_store_si128(((__m128i *)(dst + 8)), xmm5); 6327 _mm_store_si128(((__m128i *)(dst + 12)), xmm6); 6328 6329 dst += 16; 6330 src += 16; 6331 w -= 16; 6332 } 6333 6334 while (w) 6335 { 6336 *dst++ = *(src++) << 24; 6337 w--; 6338 } 6339 6340 return iter->buffer; 6341 } 6342 6343 typedef struct 6344 { 6345 pixman_format_code_t format; 6346 pixman_iter_get_scanline_t get_scanline; 6347 } fetcher_info_t; 6348 6349 static const fetcher_info_t fetchers[] = 6350 { 6351 { PIXMAN_x8r8g8b8, sse2_fetch_x8r8g8b8 }, 6352 { PIXMAN_r5g6b5, sse2_fetch_r5g6b5 }, 6353 { PIXMAN_a8, sse2_fetch_a8 }, 6354 { PIXMAN_null } 6355 }; 6356 6357 static pixman_bool_t 6358 sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) 6359 { 6360 pixman_image_t *image = iter->image; 6361 6362 #define FLAGS \ 6363 (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \ 6364 FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) 6365 6366 if ((iter->iter_flags & ITER_NARROW) && 6367 (iter->image_flags & FLAGS) == FLAGS) 6368 { 6369 const fetcher_info_t *f; 6370 6371 for (f = &fetchers[0]; f->format != PIXMAN_null; f++) 6372 { 6373 if (image->common.extended_format_code == f->format) 6374 { 6375 uint8_t *b = (uint8_t *)image->bits.bits; 6376 int s = image->bits.rowstride * 4; 6377 6378 iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8; 6379 iter->stride = s; 6380 6381 iter->get_scanline = f->get_scanline; 6382 return TRUE; 6383 } 6384 } 6385 } 6386 6387 return FALSE; 6388 } 6389 6390 #if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) 6391 __attribute__((__force_align_arg_pointer__)) 6392 #endif 6393 pixman_implementation_t * 6394 _pixman_implementation_create_sse2 (pixman_implementation_t *fallback) 6395 { 6396 pixman_implementation_t *imp = _pixman_implementation_create (fallback, sse2_fast_paths); 6397 6398 /* SSE2 constants */ 6399 mask_565_r = create_mask_2x32_128 (0x00f80000, 0x00f80000); 6400 mask_565_g1 = create_mask_2x32_128 (0x00070000, 0x00070000); 6401 mask_565_g2 = create_mask_2x32_128 (0x000000e0, 0x000000e0); 6402 mask_565_b = create_mask_2x32_128 (0x0000001f, 0x0000001f); 6403 mask_red = create_mask_2x32_128 (0x00f80000, 0x00f80000); 6404 mask_green = create_mask_2x32_128 (0x0000fc00, 0x0000fc00); 6405 mask_blue = create_mask_2x32_128 (0x000000f8, 0x000000f8); 6406 mask_565_fix_rb = create_mask_2x32_128 (0x00e000e0, 0x00e000e0); 6407 mask_565_fix_g = create_mask_2x32_128 (0x0000c000, 0x0000c000); 6408 mask_0080 = create_mask_16_128 (0x0080); 6409 mask_00ff = create_mask_16_128 (0x00ff); 6410 mask_0101 = create_mask_16_128 (0x0101); 6411 mask_ffff = create_mask_16_128 (0xffff); 6412 mask_ff000000 = create_mask_2x32_128 (0xff000000, 0xff000000); 6413 mask_alpha = create_mask_2x32_128 (0x00ff0000, 0x00000000); 6414 mask_565_rb = create_mask_2x32_128 (0x00f800f8, 0x00f800f8); 6415 mask_565_pack_multiplier = create_mask_2x32_128 (0x20000004, 0x20000004); 6416 6417 /* Set up function pointers */ 6418 imp->combine_32[PIXMAN_OP_OVER] = sse2_combine_over_u; 6419 imp->combine_32[PIXMAN_OP_OVER_REVERSE] = sse2_combine_over_reverse_u; 6420 imp->combine_32[PIXMAN_OP_IN] = sse2_combine_in_u; 6421 imp->combine_32[PIXMAN_OP_IN_REVERSE] = sse2_combine_in_reverse_u; 6422 imp->combine_32[PIXMAN_OP_OUT] = sse2_combine_out_u; 6423 imp->combine_32[PIXMAN_OP_OUT_REVERSE] = sse2_combine_out_reverse_u; 6424 imp->combine_32[PIXMAN_OP_ATOP] = sse2_combine_atop_u; 6425 imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = sse2_combine_atop_reverse_u; 6426 imp->combine_32[PIXMAN_OP_XOR] = sse2_combine_xor_u; 6427 imp->combine_32[PIXMAN_OP_ADD] = sse2_combine_add_u; 6428 6429 imp->combine_32[PIXMAN_OP_SATURATE] = sse2_combine_saturate_u; 6430 6431 imp->combine_32_ca[PIXMAN_OP_SRC] = sse2_combine_src_ca; 6432 imp->combine_32_ca[PIXMAN_OP_OVER] = sse2_combine_over_ca; 6433 imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = sse2_combine_over_reverse_ca; 6434 imp->combine_32_ca[PIXMAN_OP_IN] = sse2_combine_in_ca; 6435 imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = sse2_combine_in_reverse_ca; 6436 imp->combine_32_ca[PIXMAN_OP_OUT] = sse2_combine_out_ca; 6437 imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = sse2_combine_out_reverse_ca; 6438 imp->combine_32_ca[PIXMAN_OP_ATOP] = sse2_combine_atop_ca; 6439 imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = sse2_combine_atop_reverse_ca; 6440 imp->combine_32_ca[PIXMAN_OP_XOR] = sse2_combine_xor_ca; 6441 imp->combine_32_ca[PIXMAN_OP_ADD] = sse2_combine_add_ca; 6442 6443 imp->blt = sse2_blt; 6444 imp->fill = sse2_fill; 6445 6446 imp->src_iter_init = sse2_src_iter_init; 6447 6448 return imp; 6449 } 6450