Index: src/core/SkXfermode4f.cpp |
diff --git a/src/core/SkXfermode4f.cpp b/src/core/SkXfermode4f.cpp |
index 4e444a791a092a0015cb9ea83b12950e02d62d88..883cd1275701d55fe6792ce86519db4e665ba0ac 100644 |
--- a/src/core/SkXfermode4f.cpp |
+++ b/src/core/SkXfermode4f.cpp |
@@ -8,6 +8,7 @@ |
#include "SkPM4fPriv.h" |
#include "SkUtils.h" |
#include "SkXfermode.h" |
+#include "Sk4x4f.h" |
static SkPM4f rgba_to_pmcolor_order(const SkPM4f& x) { |
#ifdef SK_PMCOLOR_IS_BGRA |
@@ -235,81 +236,50 @@ const SkXfermode::D32Proc gProcs_Dst[] = { |
static void srcover_n_srgb_bw(uint32_t dst[], const SkPM4f src[], int count) { |
-#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 // For _mm_shuffle_epi8 |
while (count >= 4) { |
// Load 4 sRGB RGBA/BGRA 8888 dst pixels. |
// We'll write most of this as if they're RGBA, and just swizzle the src pixels to match. |
- __m128i d4 = _mm_loadu_si128((const __m128i*)dst); |
- |
- // Transpose into planar and convert each plane to float. |
- auto _ = ~0; // Shuffles in a zero byte. |
- auto dr = _mm_cvtepi32_ps( |
- _mm_shuffle_epi8(d4, _mm_setr_epi8(0,_,_,_, 4,_,_,_, 8,_,_,_,12,_,_,_))); |
- auto dg = _mm_cvtepi32_ps( |
- _mm_shuffle_epi8(d4, _mm_setr_epi8(1,_,_,_, 5,_,_,_, 9,_,_,_,13,_,_,_))); |
- auto db = _mm_cvtepi32_ps( |
- _mm_shuffle_epi8(d4, _mm_setr_epi8(2,_,_,_, 6,_,_,_,10,_,_,_,14,_,_,_))); |
- auto da = _mm_cvtepi32_ps( |
- _mm_shuffle_epi8(d4, _mm_setr_epi8(3,_,_,_, 7,_,_,_,11,_,_,_,15,_,_,_))); |
+ auto d = Sk4x4f::Transpose((const uint8_t*)dst); |
// Scale to [0,1]. |
- dr = _mm_mul_ps(dr, _mm_set1_ps(1/255.0f)); |
- dg = _mm_mul_ps(dg, _mm_set1_ps(1/255.0f)); |
- db = _mm_mul_ps(db, _mm_set1_ps(1/255.0f)); |
- da = _mm_mul_ps(da, _mm_set1_ps(1/255.0f)); |
+ d.r *= 1/255.0f; |
+ d.g *= 1/255.0f; |
+ d.b *= 1/255.0f; |
+ d.a *= 1/255.0f; |
// Apply approximate sRGB gamma correction to convert to linear (as if gamma were 2). |
- dr = _mm_mul_ps(dr, dr); |
- dg = _mm_mul_ps(dg, dg); |
- db = _mm_mul_ps(db, db); |
+ d.r *= d.r; |
+ d.g *= d.g; |
+ d.b *= d.b; |
// Load 4 linear float src pixels. |
- auto s0 = _mm_loadu_ps(src[0].fVec), |
- s1 = _mm_loadu_ps(src[1].fVec), |
- s2 = _mm_loadu_ps(src[2].fVec), |
- s3 = _mm_loadu_ps(src[3].fVec); |
- |
- // Transpose src pixels to planar too, and give the registers better names. |
- _MM_TRANSPOSE4_PS(s0, s1, s2, s3); |
- auto sr = s0, |
- sg = s1, |
- sb = s2, |
- sa = s3; |
+ auto s = Sk4x4f::Transpose(src->fVec); |
// Match color order with destination, if necessary. |
#if defined(SK_PMCOLOR_IS_BGRA) |
- SkTSwap(sr, sb); |
+ SkTSwap(s.r, s.b); |
#endif |
// Now, the meat of what we wanted to do... perform the srcover blend. |
- auto invSA = _mm_sub_ps(_mm_set1_ps(1), sa); |
- auto r = _mm_add_ps(sr, _mm_mul_ps(dr, invSA)), |
- g = _mm_add_ps(sg, _mm_mul_ps(dg, invSA)), |
- b = _mm_add_ps(sb, _mm_mul_ps(db, invSA)), |
- a = _mm_add_ps(sa, _mm_mul_ps(da, invSA)); |
+ auto invSA = 1.0f - s.a; |
+ auto r = s.r + d.r * invSA, |
+ g = s.g + d.g * invSA, |
+ b = s.b + d.b * invSA, |
+ a = s.a + d.a * invSA; |
// Convert back to sRGB and [0,255], again approximating sRGB as gamma == 2. |
- r = _mm_mul_ps(_mm_sqrt_ps(r), _mm_set1_ps(255)); |
- g = _mm_mul_ps(_mm_sqrt_ps(g), _mm_set1_ps(255)); |
- b = _mm_mul_ps(_mm_sqrt_ps(b), _mm_set1_ps(255)); |
- a = _mm_mul_ps( (a), _mm_set1_ps(255)); |
- |
- // Convert to int (with rounding) and pack back down to planar 8-bit. |
- __m128i x = _mm_packus_epi16(_mm_packus_epi16(_mm_cvtps_epi32(r), _mm_cvtps_epi32(g)), |
- _mm_packus_epi16(_mm_cvtps_epi32(b), _mm_cvtps_epi32(a))); |
- |
- // Transpose back to interlaced RGBA and write back to dst. |
- x = _mm_shuffle_epi8(x, _mm_setr_epi8(0, 4, 8, 12, |
- 1, 5, 9, 13, |
- 2, 6, 10, 14, |
- 3, 7, 11, 15)); |
- _mm_storeu_si128((__m128i*)dst, x); |
+ r = r.sqrt() * 255.0f + 0.5f; |
+ g = g.sqrt() * 255.0f + 0.5f; |
+ b = b.sqrt() * 255.0f + 0.5f; |
+ a = a * 255.0f + 0.5f; |
+ |
+ Sk4x4f{r,g,b,a}.transpose((uint8_t*)dst); |
count -= 4; |
dst += 4; |
src += 4; |
} |
-#endif |
+ |
// This should look just like the non-specialized case in srcover_n. |
for (int i = 0; i < count; ++i) { |
Sk4f s4 = src[i].to4f_pmorder(); |