Have the SSE2 version of PackARGB use common code.

The common code actually got sped-up by 25% by using the code
from PackARGB.

Change-Id: I94be6ccff2bfe02fff13c8e2698669e6a0d8fc74
This commit is contained in:
Vincent Rabaud 2017-06-20 17:01:29 +02:00
parent 7b250459d6
commit 7ca0df1363
2 changed files with 20 additions and 35 deletions

View File

@ -12,6 +12,7 @@
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h" #include "./dsp.h"
#include "./lossless.h"
#if defined(WEBP_USE_SSE2) #if defined(WEBP_USE_SSE2)
@ -19,30 +20,13 @@
#include <emmintrin.h> #include <emmintrin.h>
#include <string.h> #include <string.h>
static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
}
static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
const uint8_t* b, int len, uint32_t* out) { const uint8_t* b, int len, uint32_t* out) {
(void)a;
if (g == r + 1) { // RGBA input order. Need to swap R and B. if (g == r + 1) { // RGBA input order. Need to swap R and B.
int i = 0;
const int len_max = len & ~3; // max length processed in main loop
const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu);
assert(b == r + 2); assert(b == r + 2);
assert(a == r + 3); assert(a == r + 3);
for (; i < len_max; i += 4) { VP8LConvertBGRAToRGBA((const uint32_t*)r, len, (uint8_t*)out);
const __m128i A = _mm_loadu_si128((const __m128i*)(r + 4 * i));
const __m128i B = _mm_and_si128(A, red_blue_mask); // R 0 B 0
const __m128i C = _mm_andnot_si128(red_blue_mask, A); // 0 G 0 A
const __m128i D = _mm_shufflelo_epi16(B, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i E = _mm_shufflehi_epi16(D, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i F = _mm_or_si128(E, C);
_mm_storeu_si128((__m128i*)(out + i), F);
}
for (; i < len; ++i) {
out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
}
} else { } else {
assert(g == b + 1); assert(g == b + 1);
assert(r == b + 2); assert(r == b + 2);
@ -55,8 +39,10 @@ static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
// Entry point // Entry point
extern void VP8EncDspARGBInitSSE2(void); extern void VP8EncDspARGBInitSSE2(void);
extern void VP8LDspInitSSE2(void);
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) { WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) {
VP8LDspInitSSE2();
VP8PackARGB = PackARGB; VP8PackARGB = PackARGB;
} }

View File

@ -522,25 +522,24 @@ static void ConvertBGRAToRGB(const uint32_t* src, int num_pixels,
static void ConvertBGRAToRGBA(const uint32_t* src, static void ConvertBGRAToRGBA(const uint32_t* src,
int num_pixels, uint8_t* dst) { int num_pixels, uint8_t* dst) {
const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu);
const __m128i* in = (const __m128i*)src; const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst; __m128i* out = (__m128i*)dst;
while (num_pixels >= 8) { while (num_pixels >= 8) {
const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 const __m128i A1 = _mm_loadu_si128(in++);
const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 const __m128i A2 = _mm_loadu_si128(in++);
const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... const __m128i B1 = _mm_and_si128(A1, red_blue_mask); // R 0 B 0
const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... const __m128i B2 = _mm_and_si128(A2, red_blue_mask); // R 0 B 0
const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... const __m128i C1 = _mm_andnot_si128(red_blue_mask, A1); // 0 G 0 A
const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... const __m128i C2 = _mm_andnot_si128(red_blue_mask, A2); // 0 G 0 A
const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 const __m128i D1 = _mm_shufflelo_epi16(B1, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 const __m128i D2 = _mm_shufflelo_epi16(B2, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 const __m128i E1 = _mm_shufflehi_epi16(D1, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 const __m128i E2 = _mm_shufflehi_epi16(D2, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7 const __m128i F1 = _mm_or_si128(E1, C1);
const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7 const __m128i F2 = _mm_or_si128(E2, C2);
const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1... _mm_storeu_si128(out++, F1);
const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5... _mm_storeu_si128(out++, F2);
_mm_storeu_si128(out++, rgba0);
_mm_storeu_si128(out++, rgba4);
num_pixels -= 8; num_pixels -= 8;
} }
// left-overs // left-overs