| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include <emmintrin.h> | 8 #include <emmintrin.h> |
| 9 #include "SkBitmapProcState_opts_SSE2.h" | 9 #include "SkBitmapProcState_opts_SSE2.h" |
| 10 #include "SkBlitRow_opts_SSE2.h" | 10 #include "SkBlitRow_opts_SSE2.h" |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 } | 225 } |
| 226 | 226 |
| 227 while (count > 0) { | 227 while (count > 0) { |
| 228 *dst = SkBlendARGB32(*src, *dst, alpha); | 228 *dst = SkBlendARGB32(*src, *dst, alpha); |
| 229 src++; | 229 src++; |
| 230 dst++; | 230 dst++; |
| 231 count--; | 231 count--; |
| 232 } | 232 } |
| 233 } | 233 } |
| 234 | 234 |
| 235 #define SK_SUPPORT_LEGACY_COLOR32_MATHx | |
| 236 | |
| 237 /* SSE2 version of Color32() | |
| 238 * portable version is in core/SkBlitRow_D32.cpp | |
| 239 */ | |
| 240 // Color32 and its SIMD specializations use the blend_256_round_alt algorithm | |
| 241 // from tests/BlendTest.cpp. It's not quite perfect, but it's never wrong in th
e | |
| 242 // interesting edge cases, and it's quite a bit faster than blend_perfect. | |
| 243 // | |
| 244 // blend_256_round_alt is our currently blessed algorithm. Please use it or an
analogous one. | |
| 245 void Color32_SSE2(SkPMColor dst[], const SkPMColor src[], int count, SkPMColor c
olor) { | |
| 246 switch (SkGetPackedA32(color)) { | |
| 247 case 0: memmove(dst, src, count * sizeof(SkPMColor)); return; | |
| 248 case 255: sk_memset32(dst, color, count); return; | |
| 249 } | |
| 250 | |
| 251 __m128i colorHigh = _mm_unpacklo_epi8(_mm_setzero_si128(), _mm_set1_epi32(co
lor)); | |
| 252 #ifdef SK_SUPPORT_LEGACY_COLOR32_MATH // blend_256_plus1_trunc, busted | |
| 253 __m128i colorAndRound = colorHigh; | |
| 254 #else // blend_256_round_alt, good | |
| 255 __m128i colorAndRound = _mm_add_epi16(colorHigh, _mm_set1_epi16(128)); | |
| 256 #endif | |
| 257 | |
| 258 unsigned invA = 255 - SkGetPackedA32(color); | |
| 259 #ifdef SK_SUPPORT_LEGACY_COLOR32_MATH // blend_256_plus1_trunc, busted | |
| 260 __m128i invA16 = _mm_set1_epi16(invA); | |
| 261 #else // blend_256_round_alt, good | |
| 262 SkASSERT(invA + (invA >> 7) < 256); // We should still fit in the low byte
here. | |
| 263 __m128i invA16 = _mm_set1_epi16(invA + (invA >> 7)); | |
| 264 #endif | |
| 265 | |
| 266 // Does the core work of blending color onto 4 pixels, returning the resulti
ng 4 pixels. | |
| 267 auto kernel = [&](const __m128i& src4) -> __m128i { | |
| 268 __m128i lo = _mm_mullo_epi16(invA16, _mm_unpacklo_epi8(src4, _mm_setzero
_si128())), | |
| 269 hi = _mm_mullo_epi16(invA16, _mm_unpackhi_epi8(src4, _mm_setzero
_si128())); | |
| 270 return _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(colorAndRound, lo),
8), | |
| 271 _mm_srli_epi16(_mm_add_epi16(colorAndRound, hi),
8)); | |
| 272 }; | |
| 273 | |
| 274 while (count >= 8) { | |
| 275 __m128i dst0 = kernel(_mm_loadu_si128((const __m128i*)(src+0))), | |
| 276 dst4 = kernel(_mm_loadu_si128((const __m128i*)(src+4))); | |
| 277 _mm_storeu_si128((__m128i*)(dst+0), dst0); | |
| 278 _mm_storeu_si128((__m128i*)(dst+4), dst4); | |
| 279 src += 8; | |
| 280 dst += 8; | |
| 281 count -= 8; | |
| 282 } | |
| 283 if (count >= 4) { | |
| 284 _mm_storeu_si128((__m128i*)dst, kernel(_mm_loadu_si128((const __m128i*)s
rc))); | |
| 285 src += 4; | |
| 286 dst += 4; | |
| 287 count -= 4; | |
| 288 } | |
| 289 if (count >= 2) { | |
| 290 _mm_storel_epi64((__m128i*)dst, kernel(_mm_loadl_epi64((const __m128i*)s
rc))); | |
| 291 src += 2; | |
| 292 dst += 2; | |
| 293 count -= 2; | |
| 294 } | |
| 295 if (count >= 1) { | |
| 296 *dst = _mm_cvtsi128_si32(kernel(_mm_cvtsi32_si128(*src))); | |
| 297 } | |
| 298 } | |
| 299 | |
| 300 void Color32A_D565_SSE2(uint16_t dst[], SkPMColor src, int count, int x, int y)
{ | 235 void Color32A_D565_SSE2(uint16_t dst[], SkPMColor src, int count, int x, int y)
{ |
| 301 SkASSERT(count > 0); | 236 SkASSERT(count > 0); |
| 302 | 237 |
| 303 uint32_t src_expand = (SkGetPackedG32(src) << 24) | | 238 uint32_t src_expand = (SkGetPackedG32(src) << 24) | |
| 304 (SkGetPackedR32(src) << 13) | | 239 (SkGetPackedR32(src) << 13) | |
| 305 (SkGetPackedB32(src) << 2); | 240 (SkGetPackedB32(src) << 2); |
| 306 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3; | 241 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3; |
| 307 | 242 |
| 308 // Check if we have enough pixels to run SIMD | 243 // Check if we have enough pixels to run SIMD |
| 309 if (count >= (int)(8 + (((16 - (size_t)dst) & 0x0F) >> 1))) { | 244 if (count >= (int)(8 + (((16 - (size_t)dst) & 0x0F) >> 1))) { |
| (...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 uint32_t dst_expanded = SkExpand_rgb_16(*dst); | 1158 uint32_t dst_expanded = SkExpand_rgb_16(*dst); |
| 1224 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3); | 1159 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3); |
| 1225 // now src and dst expanded are in g:11 r:10 x:1 b:10 | 1160 // now src and dst expanded are in g:11 r:10 x:1 b:10 |
| 1226 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5); | 1161 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5); |
| 1227 } | 1162 } |
| 1228 dst += 1; | 1163 dst += 1; |
| 1229 DITHER_INC_X(x); | 1164 DITHER_INC_X(x); |
| 1230 } while (--count != 0); | 1165 } while (--count != 0); |
| 1231 } | 1166 } |
| 1232 } | 1167 } |
| OLD | NEW |