--- src/opts/SkSwizzler_opts.inc.orig +++ src/opts/SkSwizzler_opts.inc @@ -96,6 +96,21 @@ #endif static void RGBA_to_rgbA_portable(uint32_t* dst, const uint32_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t r = (src[i] >> 24) & 0xFF, + g = (src[i] >> 16) & 0xFF, + b = (src[i] >> 8) & 0xFF, + a = (src[i] >> 0) & 0xFF; + b = (b*a+127)/255; + g = (g*a+127)/255; + r = (r*a+127)/255; + dst[i] = (uint32_t)r << 24 + | (uint32_t)g << 16 + | (uint32_t)b << 8 + | (uint32_t)a << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t a = (src[i] >> 24) & 0xFF, b = (src[i] >> 16) & 0xFF, @@ -109,6 +124,7 @@ | (uint32_t)g << 8 | (uint32_t)r << 0; } +#endif } // RP uses the following rounding routines in store_8888. There are three different @@ -156,26 +172,31 @@ return pixel_round_as_RP(answer); } +// Pack four already-unpremultiplied channels so that c00, c08, c16 and a land in +// ascending memory order. (On little endian that is shifts 0/8/16/24; on big endian +// the same memory order needs the opposite shifts.) +SI uint32_t pack_CCCA(uint32_t c00, uint32_t c08, uint32_t c16, uint32_t a) { +#ifdef SK_CPU_BENDIAN + return c00 << 24 | c08 << 16 | c16 << 8 | a; +#else + return a << 24 | c16 << 16 | c08 << 8 | c00; +#endif +} + SI uint32_t rgbA_to_CCCA(float c00, float c08, float c16, float a) { if constexpr (kFastUnpremul) { const float reciprocalA = reciprocal_alpha_times_255(a); auto unpremul = [reciprocalA](float c) -> uint32_t { return unpremul_quick(reciprocalA, c); }; - return (uint32_t) a << 24 - | unpremul(c16) << 16 - | unpremul(c08) << 8 - | unpremul(c00) << 0; + return pack_CCCA(unpremul(c00), unpremul(c08), unpremul(c16), (uint32_t)a); } else { const float normalizedA = a * (1.0f / 255.0f); const float reciprocalA = reciprocal_alpha(normalizedA); auto unpremul = [reciprocalA](float c) -> uint32_t { return unpremul_simulating_RP(reciprocalA, c); }; - return (uint32_t) a << 24 - | unpremul(c16) << 16 - | unpremul(c08) << 8 - | unpremul(c00) << 0; + return pack_CCCA(unpremul(c00), unpremul(c08), unpremul(c16), (uint32_t)a); } } @@ -183,10 +204,17 @@ for (int i = 0; i < count; i++) { const uint32_t p = src[i]; +#ifdef SK_CPU_BENDIAN + const float r = (p >> 24) & 0xFF, + g = (p >> 16) & 0xFF, + b = (p >> 8) & 0xFF, + a = (p >> 0) & 0xFF; +#else const float a = (p >> 24) & 0xFF, b = (p >> 16) & 0xFF, g = (p >> 8) & 0xFF, r = (p >> 0) & 0xFF; +#endif dst[i] = rgbA_to_CCCA(r, g, b, a); } @@ -196,16 +224,38 @@ for (int i = 0; i < count; i++) { const uint32_t p = src[i]; +#ifdef SK_CPU_BENDIAN + const uint32_t r = (p >> 24) & 0xFF, + g = (p >> 16) & 0xFF, + b = (p >> 8) & 0xFF, + a = (p >> 0) & 0xFF; +#else const uint32_t a = (p >> 24) & 0xFF, b = (p >> 16) & 0xFF, g = (p >> 8) & 0xFF, r = (p >> 0) & 0xFF; +#endif dst[i] = rgbA_to_CCCA(b, g, r, a); } } static void RGBA_to_bgrA_portable(uint32_t* dst, const uint32_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t r = (src[i] >> 24) & 0xFF, + g = (src[i] >> 16) & 0xFF, + b = (src[i] >> 8) & 0xFF, + a = (src[i] >> 0) & 0xFF; + b = (b*a+127)/255; + g = (g*a+127)/255; + r = (r*a+127)/255; + dst[i] = (uint32_t)b << 24 + | (uint32_t)g << 16 + | (uint32_t)r << 8 + | (uint32_t)a << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t a = (src[i] >> 24) & 0xFF, b = (src[i] >> 16) & 0xFF, @@ -219,9 +269,22 @@ | (uint32_t)g << 8 | (uint32_t)b << 0; } +#endif } static void RGBA_to_BGRA_portable(uint32_t* dst, const uint32_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t r = (src[i] >> 24) & 0xFF, + g = (src[i] >> 16) & 0xFF, + b = (src[i] >> 8) & 0xFF, + a = (src[i] >> 0) & 0xFF; + dst[i] = (uint32_t)b << 24 + | (uint32_t)g << 16 + | (uint32_t)r << 8 + | (uint32_t)a << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t a = (src[i] >> 24) & 0xFF, b = (src[i] >> 16) & 0xFF, @@ -232,9 +295,21 @@ | (uint32_t)g << 8 | (uint32_t)b << 0; } +#endif } static void grayA_to_RGBA_portable(uint32_t dst[], const uint8_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t g = src[0], + a = src[1]; + src += 2; + dst[i] = (uint32_t)g << 24 + | (uint32_t)g << 16 + | (uint32_t)g << 8 + | (uint32_t)a << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t g = src[0], a = src[1]; @@ -244,9 +319,22 @@ | (uint32_t)g << 8 | (uint32_t)g << 0; } +#endif } static void grayA_to_rgbA_portable(uint32_t dst[], const uint8_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t g = src[0], + a = src[1]; + src += 2; + g = (g*a+127)/255; + dst[i] = (uint32_t)g << 24 + | (uint32_t)g << 16 + | (uint32_t)g << 8 + | (uint32_t)a << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t g = src[0], a = src[1]; @@ -257,9 +345,26 @@ | (uint32_t)g << 8 | (uint32_t)g << 0; } +#endif } static void inverted_CMYK_to_RGB1_portable(uint32_t* dst, const uint32_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t c = (src[i] >> 24) & 0xFF, + m = (src[i] >> 16) & 0xFF, + y = (src[i] >> 8) & 0xFF, + k = (src[i] >> 0) & 0xFF; + // See comments in SkSwizzler.cpp for details on the conversion formula. + uint8_t b = (y*k+127)/255, + g = (m*k+127)/255, + r = (c*k+127)/255; + dst[i] = (uint32_t) r << 24 + | (uint32_t) g << 16 + | (uint32_t) b << 8 + | (uint32_t)0xFF << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t k = (src[i] >> 24) & 0xFF, y = (src[i] >> 16) & 0xFF, @@ -274,9 +379,25 @@ | (uint32_t) g << 8 | (uint32_t) r << 0; } +#endif } static void inverted_CMYK_to_BGR1_portable(uint32_t* dst, const uint32_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t c = (src[i] >> 24) & 0xFF, + m = (src[i] >> 16) & 0xFF, + y = (src[i] >> 8) & 0xFF, + k = (src[i] >> 0) & 0xFF; + uint8_t b = (y*k+127)/255, + g = (m*k+127)/255, + r = (c*k+127)/255; + dst[i] = (uint32_t) b << 24 + | (uint32_t) g << 16 + | (uint32_t) r << 8 + | (uint32_t)0xFF << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t k = (src[i] >> 24) & 0xFF, y = (src[i] >> 16) & 0xFF, @@ -290,6 +411,7 @@ | (uint32_t) g << 8 | (uint32_t) b << 0; } +#endif } #if defined(SK_ARM_HAS_NEON) @@ -1619,12 +1741,21 @@ // Basically as above, but we found no benefit from AVX-512 for gray_to_RGB1. static void gray_to_RGB1_portable(uint32_t dst[], const uint8_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + dst[i] = (uint32_t)src[i] << 24 + | (uint32_t)src[i] << 16 + | (uint32_t)src[i] << 8 + | (uint32_t)0xFF << 0; + } +#else for (int i = 0; i < count; i++) { dst[i] = (uint32_t)0xFF << 24 | (uint32_t)src[i] << 16 | (uint32_t)src[i] << 8 | (uint32_t)src[i] << 0; } +#endif } #if defined(SK_ARM_HAS_NEON) void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) { @@ -1803,6 +1934,18 @@ // Again as above, this time not even finding benefit from AVX2 for RGB_to_{RGB,BGR}1. static void RGB_to_RGB1_portable(uint32_t dst[], const uint8_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t r = src[0], + g = src[1], + b = src[2]; + src += 3; + dst[i] = (uint32_t)r << 24 + | (uint32_t)g << 16 + | (uint32_t)b << 8 + | (uint32_t)0xFF << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t r = src[0], g = src[1], @@ -1813,8 +1956,21 @@ | (uint32_t)g << 8 | (uint32_t)r << 0; } +#endif } static void RGB_to_BGR1_portable(uint32_t dst[], const uint8_t* src, int count) { +#ifdef SK_CPU_BENDIAN + for (int i = 0; i < count; i++) { + uint8_t r = src[0], + g = src[1], + b = src[2]; + src += 3; + dst[i] = (uint32_t)b << 24 + | (uint32_t)g << 16 + | (uint32_t)r << 8 + | (uint32_t)0xFF << 0; + } +#else for (int i = 0; i < count; i++) { uint8_t r = src[0], g = src[1], @@ -1825,6 +1981,7 @@ | (uint32_t)g << 8 | (uint32_t)b << 0; } +#endif } #if defined(SK_ARM_HAS_NEON) static void insert_alpha_should_swaprb(bool kSwapRB,