mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
faster CollectColorXXXTransforms_SSE41
3/4% faster overall. Change-Id: If555c5530238ca0342b8d97b0d708b1bdc888d3f
This commit is contained in:
parent
652aa34424
commit
01b38ee19a
@ -44,46 +44,47 @@ static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Color Transform
|
// Color Transform
|
||||||
|
|
||||||
#define SPAN 8
|
#define MK_CST_16(HI, LO) \
|
||||||
|
_mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff)))
|
||||||
|
|
||||||
static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride,
|
static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride,
|
||||||
int tile_width, int tile_height,
|
int tile_width, int tile_height,
|
||||||
int green_to_blue, int red_to_blue,
|
int green_to_blue, int red_to_blue,
|
||||||
int histo[]) {
|
int histo[]) {
|
||||||
const __m128i mults_r = _mm_set1_epi16(CST_5b(red_to_blue));
|
const __m128i mult =
|
||||||
const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_blue));
|
MK_CST_16(CST_5b(red_to_blue) + 256,CST_5b(green_to_blue));
|
||||||
const __m128i mask_g = _mm_set1_epi16((short)0xff00); // green mask
|
const __m128i perm =
|
||||||
const __m128i mask_gb = _mm_set1_epi32(0xffff); // green/blue mask
|
_mm_setr_epi8(-1, 1, -1, 2, -1, 5, -1, 6, -1, 9, -1, 10, -1, 13, -1, 14);
|
||||||
const __m128i mask_b = _mm_set1_epi16(0x00ff); // blue mask
|
if (tile_width >= 4) {
|
||||||
const __m128i shuffler_lo = _mm_setr_epi8(-1, 2, -1, 6, -1, 10, -1, 14, -1,
|
int y;
|
||||||
-1, -1, -1, -1, -1, -1, -1);
|
for (y = 0; y < tile_height; ++y) {
|
||||||
const __m128i shuffler_hi = _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1,
|
const uint32_t* const src = argb + y * stride;
|
||||||
2, -1, 6, -1, 10, -1, 14);
|
const __m128i A1 = _mm_loadu_si128((const __m128i*)src);
|
||||||
int y;
|
const __m128i B1 = _mm_shuffle_epi8(A1, perm);
|
||||||
for (y = 0; y < tile_height; ++y) {
|
const __m128i C1 = _mm_mulhi_epi16(B1, mult);
|
||||||
const uint32_t* const src = argb + y * stride;
|
const __m128i D1 = _mm_sub_epi16(A1, C1);
|
||||||
int i, x;
|
__m128i E = _mm_add_epi16(_mm_srli_epi32(D1, 16), D1);
|
||||||
for (x = 0; x + SPAN <= tile_width; x += SPAN) {
|
int x;
|
||||||
uint16_t values[SPAN];
|
for (x = 4; x + 4 <= tile_width; x += 4) {
|
||||||
const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
|
const __m128i A2 = _mm_loadu_si128((const __m128i*)(src + x));
|
||||||
const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
|
__m128i B2, C2, D2;
|
||||||
const __m128i r0 = _mm_shuffle_epi8(in0, shuffler_lo);
|
++histo[_mm_extract_epi8(E, 0)];
|
||||||
const __m128i r1 = _mm_shuffle_epi8(in1, shuffler_hi);
|
B2 = _mm_shuffle_epi8(A2, perm);
|
||||||
const __m128i r = _mm_or_si128(r0, r1); // r 0
|
++histo[_mm_extract_epi8(E, 4)];
|
||||||
const __m128i gb0 = _mm_and_si128(in0, mask_gb);
|
C2 = _mm_mulhi_epi16(B2, mult);
|
||||||
const __m128i gb1 = _mm_and_si128(in1, mask_gb);
|
++histo[_mm_extract_epi8(E, 8)];
|
||||||
const __m128i gb = _mm_packus_epi32(gb0, gb1); // g b
|
D2 = _mm_sub_epi16(A2, C2);
|
||||||
const __m128i g = _mm_and_si128(gb, mask_g); // g 0
|
++histo[_mm_extract_epi8(E, 12)];
|
||||||
const __m128i A = _mm_mulhi_epi16(r, mults_r); // x dbr
|
E = _mm_add_epi16(_mm_srli_epi32(D2, 16), D2);
|
||||||
const __m128i B = _mm_mulhi_epi16(g, mults_g); // x dbg
|
}
|
||||||
const __m128i C = _mm_sub_epi8(gb, B); // x b'
|
++histo[_mm_extract_epi8(E, 0)];
|
||||||
const __m128i D = _mm_sub_epi8(C, A); // x b''
|
++histo[_mm_extract_epi8(E, 4)];
|
||||||
const __m128i E = _mm_and_si128(D, mask_b); // 0 b''
|
++histo[_mm_extract_epi8(E, 8)];
|
||||||
_mm_storeu_si128((__m128i*)values, E);
|
++histo[_mm_extract_epi8(E, 12)];
|
||||||
for (i = 0; i < SPAN; ++i) ++histo[values[i]];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const int left_over = tile_width & (SPAN - 1);
|
const int left_over = tile_width & 3;
|
||||||
if (left_over > 0) {
|
if (left_over > 0) {
|
||||||
VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride,
|
VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride,
|
||||||
left_over, tile_height,
|
left_over, tile_height,
|
||||||
@ -95,33 +96,37 @@ static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride,
|
|||||||
static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride,
|
static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride,
|
||||||
int tile_width, int tile_height,
|
int tile_width, int tile_height,
|
||||||
int green_to_red, int histo[]) {
|
int green_to_red, int histo[]) {
|
||||||
const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_red));
|
|
||||||
const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
|
|
||||||
const __m128i mask = _mm_set1_epi16(0xff);
|
|
||||||
|
|
||||||
int y;
|
const __m128i mult = MK_CST_16(0, CST_5b(green_to_red));
|
||||||
for (y = 0; y < tile_height; ++y) {
|
const __m128i mask_g = _mm_set1_epi32(0x0000ff00);
|
||||||
const uint32_t* const src = argb + y * stride;
|
if (tile_width >= 4) {
|
||||||
int i, x;
|
int y;
|
||||||
for (x = 0; x + SPAN <= tile_width; x += SPAN) {
|
for (y = 0; y < tile_height; ++y) {
|
||||||
uint16_t values[SPAN];
|
const uint32_t* const src = argb + y * stride;
|
||||||
const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
|
const __m128i A1 = _mm_loadu_si128((const __m128i*)src);
|
||||||
const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
|
const __m128i B1 = _mm_and_si128(A1, mask_g);
|
||||||
const __m128i g0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
|
const __m128i C1 = _mm_madd_epi16(B1, mult);
|
||||||
const __m128i g1 = _mm_and_si128(in1, mask_g);
|
__m128i D = _mm_sub_epi16(A1, C1);
|
||||||
const __m128i g = _mm_packus_epi32(g0, g1); // g 0
|
int x;
|
||||||
const __m128i A0 = _mm_srli_epi32(in0, 16); // 0 0 | x r
|
for (x = 4; x + 4 <= tile_width; x += 4) {
|
||||||
const __m128i A1 = _mm_srli_epi32(in1, 16);
|
const __m128i A2 = _mm_loadu_si128((const __m128i*)(src + x));
|
||||||
const __m128i A = _mm_packus_epi32(A0, A1); // x r
|
__m128i B2, C2;
|
||||||
const __m128i B = _mm_mulhi_epi16(g, mults_g); // x dr
|
++histo[_mm_extract_epi8(D, 2)];
|
||||||
const __m128i C = _mm_sub_epi8(A, B); // x r'
|
B2 = _mm_and_si128(A2, mask_g);
|
||||||
const __m128i D = _mm_and_si128(C, mask); // 0 r'
|
++histo[_mm_extract_epi8(D, 6)];
|
||||||
_mm_storeu_si128((__m128i*)values, D);
|
C2 = _mm_madd_epi16(B2, mult);
|
||||||
for (i = 0; i < SPAN; ++i) ++histo[values[i]];
|
++histo[_mm_extract_epi8(D, 10)];
|
||||||
|
++histo[_mm_extract_epi8(D, 14)];
|
||||||
|
D = _mm_sub_epi16(A2, C2);
|
||||||
|
}
|
||||||
|
++histo[_mm_extract_epi8(D, 2)];
|
||||||
|
++histo[_mm_extract_epi8(D, 6)];
|
||||||
|
++histo[_mm_extract_epi8(D, 10)];
|
||||||
|
++histo[_mm_extract_epi8(D, 14)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const int left_over = tile_width & (SPAN - 1);
|
const int left_over = tile_width & 3;
|
||||||
if (left_over > 0) {
|
if (left_over > 0) {
|
||||||
VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride,
|
VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride,
|
||||||
left_over, tile_height, green_to_red,
|
left_over, tile_height, green_to_red,
|
||||||
@ -130,6 +135,8 @@ static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef MK_CST_16
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Entry point
|
// Entry point
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user