mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-16 22:09:57 +02:00
introduce WebPMemToUint32 and WebPUint32ToMem for memory access
it uses memcpy() when unaligned memory write is tricky Change-Id: I5d966ca9d19e9b43ac90140fa487824116982874
This commit is contained in:
@ -19,7 +19,6 @@
|
||||
|
||||
#include "../enc/cost.h"
|
||||
#include "../enc/vp8enci.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Quite useful macro for debugging. Left here for convenience.
|
||||
@ -50,16 +49,6 @@ static void PrintReg(const __m128i r, const char* const name, int size) {
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// util for unaligned loads.
|
||||
|
||||
// memcpy() is the safe way of moving potentially unaligned 32b memory.
|
||||
static WEBP_INLINE uint32_t MemToUint32(const uint8_t* const ptr) {
|
||||
uint32_t A;
|
||||
memcpy(&A, (const int*)ptr, sizeof(A));
|
||||
return A;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Transforms (Paragraph 14.4)
|
||||
|
||||
@ -247,10 +236,10 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
|
||||
ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
|
||||
} else {
|
||||
// Load four bytes/pixels per line.
|
||||
ref0 = _mm_cvtsi32_si128(MemToUint32(&ref[0 * BPS]));
|
||||
ref1 = _mm_cvtsi32_si128(MemToUint32(&ref[1 * BPS]));
|
||||
ref2 = _mm_cvtsi32_si128(MemToUint32(&ref[2 * BPS]));
|
||||
ref3 = _mm_cvtsi32_si128(MemToUint32(&ref[3 * BPS]));
|
||||
ref0 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[0 * BPS]));
|
||||
ref1 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[1 * BPS]));
|
||||
ref2 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[2 * BPS]));
|
||||
ref3 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[3 * BPS]));
|
||||
}
|
||||
// Convert to 16b.
|
||||
ref0 = _mm_unpacklo_epi8(ref0, zero);
|
||||
@ -276,10 +265,10 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
|
||||
_mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3);
|
||||
} else {
|
||||
// Store four bytes/pixels per line.
|
||||
*((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(ref0);
|
||||
*((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(ref1);
|
||||
*((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(ref2);
|
||||
*((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(ref3);
|
||||
WebPUint32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0));
|
||||
WebPUint32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1));
|
||||
WebPUint32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2));
|
||||
WebPUint32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -821,7 +810,7 @@ static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical
|
||||
const uint32_t vals = _mm_cvtsi128_si32(avg);
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
*(uint32_t*)(dst + i * BPS) = vals;
|
||||
WebPUint32ToMem(dst + i * BPS, vals);
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,10 +820,10 @@ static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal
|
||||
const int J = top[-3];
|
||||
const int K = top[-4];
|
||||
const int L = top[-5];
|
||||
*(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(X, I, J);
|
||||
*(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(I, J, K);
|
||||
*(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(J, K, L);
|
||||
*(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(K, L, L);
|
||||
WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J));
|
||||
WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K));
|
||||
WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L));
|
||||
WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L));
|
||||
}
|
||||
|
||||
static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) {
|
||||
@ -854,10 +843,10 @@ static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left
|
||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
|
||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
|
||||
*(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcdefg );
|
||||
*(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1));
|
||||
*(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2));
|
||||
*(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3));
|
||||
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
|
||||
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
||||
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
||||
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
||||
}
|
||||
|
||||
static WEBP_INLINE void VR4(uint8_t* dst,
|
||||
@ -876,10 +865,10 @@ static WEBP_INLINE void VR4(uint8_t* dst,
|
||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
|
||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||
const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
|
||||
*(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcd );
|
||||
*(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( efgh );
|
||||
*(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1));
|
||||
*(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1));
|
||||
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
|
||||
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
|
||||
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
|
||||
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
|
||||
|
||||
// these two are hard to implement in SSE2, so we keep the C-version:
|
||||
DST(0, 2) = AVG3(J, I, X);
|
||||
@ -902,10 +891,10 @@ static WEBP_INLINE void VL4(uint8_t* dst,
|
||||
const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
|
||||
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
|
||||
const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
|
||||
*(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( avg1 );
|
||||
*(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( avg4 );
|
||||
*(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1));
|
||||
*(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1));
|
||||
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
|
||||
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
|
||||
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
|
||||
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
|
||||
|
||||
// these two are hard to get and irregular
|
||||
DST(3, 2) = (extra_out >> 0) & 0xff;
|
||||
@ -922,10 +911,10 @@ static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right
|
||||
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
|
||||
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
|
||||
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
|
||||
*(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32( abcdefg );
|
||||
*(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1));
|
||||
*(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2));
|
||||
*(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3));
|
||||
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
|
||||
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
|
||||
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
|
||||
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
|
||||
}
|
||||
|
||||
static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) {
|
||||
@ -968,14 +957,14 @@ static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) {
|
||||
|
||||
static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) {
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
const __m128i top_values = _mm_cvtsi32_si128(MemToUint32(top));
|
||||
const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top));
|
||||
const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
|
||||
int y;
|
||||
for (y = 0; y < 4; ++y, dst += BPS) {
|
||||
const int val = top[-2 - y] - top[-1];
|
||||
const __m128i base = _mm_set1_epi16(val);
|
||||
const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
|
||||
*(int*)dst = _mm_cvtsi128_si32(out);
|
||||
WebPUint32ToMem(dst, _mm_cvtsi128_si32(out));
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user