mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
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:
parent
7b250459d6
commit
7ca0df1363
@ -12,6 +12,7 @@
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include "./dsp.h"
|
||||
#include "./lossless.h"
|
||||
|
||||
#if defined(WEBP_USE_SSE2)
|
||||
|
||||
@ -19,30 +20,13 @@
|
||||
#include <emmintrin.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,
|
||||
const uint8_t* b, int len, uint32_t* out) {
|
||||
(void)a;
|
||||
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(a == r + 3);
|
||||
for (; i < len_max; i += 4) {
|
||||
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]);
|
||||
}
|
||||
VP8LConvertBGRAToRGBA((const uint32_t*)r, len, (uint8_t*)out);
|
||||
} else {
|
||||
assert(g == b + 1);
|
||||
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
|
||||
|
||||
extern void VP8EncDspARGBInitSSE2(void);
|
||||
extern void VP8LDspInitSSE2(void);
|
||||
|
||||
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) {
|
||||
VP8LDspInitSSE2();
|
||||
VP8PackARGB = PackARGB;
|
||||
}
|
||||
|
||||
|
@ -522,25 +522,24 @@ static void ConvertBGRAToRGB(const uint32_t* src, int num_pixels,
|
||||
|
||||
static void ConvertBGRAToRGBA(const uint32_t* src,
|
||||
int num_pixels, uint8_t* dst) {
|
||||
const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu);
|
||||
const __m128i* in = (const __m128i*)src;
|
||||
__m128i* out = (__m128i*)dst;
|
||||
while (num_pixels >= 8) {
|
||||
const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
|
||||
const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
|
||||
const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
|
||||
const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
|
||||
const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
|
||||
const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
|
||||
const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
|
||||
const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
|
||||
const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
|
||||
const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
|
||||
const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7
|
||||
const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7
|
||||
const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1...
|
||||
const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5...
|
||||
_mm_storeu_si128(out++, rgba0);
|
||||
_mm_storeu_si128(out++, rgba4);
|
||||
const __m128i A1 = _mm_loadu_si128(in++);
|
||||
const __m128i A2 = _mm_loadu_si128(in++);
|
||||
const __m128i B1 = _mm_and_si128(A1, red_blue_mask); // R 0 B 0
|
||||
const __m128i B2 = _mm_and_si128(A2, red_blue_mask); // R 0 B 0
|
||||
const __m128i C1 = _mm_andnot_si128(red_blue_mask, A1); // 0 G 0 A
|
||||
const __m128i C2 = _mm_andnot_si128(red_blue_mask, A2); // 0 G 0 A
|
||||
const __m128i D1 = _mm_shufflelo_epi16(B1, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
const __m128i D2 = _mm_shufflelo_epi16(B2, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
const __m128i E1 = _mm_shufflehi_epi16(D1, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
const __m128i E2 = _mm_shufflehi_epi16(D2, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
const __m128i F1 = _mm_or_si128(E1, C1);
|
||||
const __m128i F2 = _mm_or_si128(E2, C2);
|
||||
_mm_storeu_si128(out++, F1);
|
||||
_mm_storeu_si128(out++, F2);
|
||||
num_pixels -= 8;
|
||||
}
|
||||
// left-overs
|
||||
|
Loading…
Reference in New Issue
Block a user