Add AVX2 row functions for RGB565, ARGB1555, and ARGB4444

On Icelake:
Was C
I420ToARGB1555_Opt (1230 ms)
I420ToARGB4444_Opt (1195 ms)
I420ToRGB565_Opt (1141 ms)

Now AVX2
I420ToARGB1555_Opt (372 ms)
I420ToARGB4444_Opt (397 ms)
I420ToRGB565_Opt (347 ms)
I420ToRGB24Filter_Opt (567 ms)
I420ToRGB565Dither_Opt (418 ms)
I420ToARGBFilter_Opt (381 ms)
I420ToRGBA_Opt (304 ms)
I420ToBGRA_Opt (296 ms)
I420ToARGB_Opt (257 ms)
I420ToABGR_Opt (254 ms)
I420ToAR30_Opt (215 ms)
I420ToRGB24_Opt (205 ms)
I420ToRAW_Opt (193 ms)

Bug: None
Change-Id: I36cf95d29ba85ae63c549fef7f55cb1fe0f95d8e
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8282746
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
This commit is contained in:
Frank Barchard 2026-08-24 19:07:15 -07:00 committed by libyuv-scoped@luci-project-accounts.iam.gserviceaccount.com
parent ae48f8dd61
commit a0fa632939
7 changed files with 372 additions and 7 deletions

View File

@ -1,6 +1,6 @@
Name: libyuv
URL: https://chromium.googlesource.com/libyuv/libyuv/
Version: 1963
Version: 1964
Revision: DEPS
License: BSD-3-Clause
License File: LICENSE

View File

@ -47,6 +47,9 @@ extern "C" {
#define HAS_I422TOARGBROW_SSSE3
#define HAS_I422TORGB24ROW_SSSE3
#define HAS_I422TORGBBAROW_SSSE3
#define HAS_I422TORGB565ROW_SSSE3
#define HAS_I422TOARGB1555ROW_SSSE3
#define HAS_I422TOARGB4444ROW_SSSE3
#define HAS_I422TOUYVYROW_SSE2
#define HAS_I422TOYUY2ROW_SSE2
#define HAS_I444TOARGBROW_SSSE3
@ -55,6 +58,7 @@ extern "C" {
#define HAS_MIRRORROW_SSSE3
#define HAS_NV12TOARGBROW_SSSE3
#define HAS_NV12TORGB24ROW_SSSE3
#define HAS_NV12TORGB565ROW_SSSE3
#define HAS_NV21TOARGBROW_SSSE3
#define HAS_NV21TORGB24ROW_SSSE3
#define HAS_RAWTOARGBROW_SSSE3
@ -158,6 +162,9 @@ extern "C" {
#define HAS_I422TOARGBROW_AVX2
#define HAS_I422TORGB24ROW_AVX2
#define HAS_I422TORGBAROW_AVX2
#define HAS_I422TORGB565ROW_AVX2
#define HAS_I422TOARGB1555ROW_AVX2
#define HAS_I422TOARGB4444ROW_AVX2
#define HAS_I444TOARGBROW_AVX2
#define HAS_I444TORGB24ROW_AVX2
#define HAS_J400TOARGBROW_AVX2
@ -165,6 +172,7 @@ extern "C" {
#define HAS_MIRRORSPLITUVROW_AVX2
#define HAS_NV12TOARGBROW_AVX2
#define HAS_NV12TORGB24ROW_AVX2
#define HAS_NV12TORGB565ROW_AVX2
#define HAS_NV21TOARGBROW_AVX2
#define HAS_NV21TORGB24ROW_AVX2
#define HAS_SPLITUVROW_AVX2
@ -272,6 +280,9 @@ extern "C" {
#define HAS_ARGBTOAR64ROW_AVX2
#define HAS_ARGBTORAWROW_AVX2
#define HAS_ARGBTORGB24ROW_AVX2
#define HAS_ARGBTORGB565ROW_AVX2
#define HAS_ARGBTOARGB1555ROW_AVX2
#define HAS_ARGBTOARGB4444ROW_AVX2
#define HAS_ARGBTOUVMATRIXROW_AVX2
#define HAS_RGBTOUVMATRIXROW_AVX2
#define HAS_RGB565TOUVMATRIXROW_AVX2
@ -348,6 +359,14 @@ extern "C" {
#define HAS_ARGB1555TOARGBROW_AVX2
#define HAS_ARGB4444TOARGBROW_AVX2
#define HAS_ARGBSHUFFLEROW_AVX2
#define HAS_ARGBTORGB565ROW_AVX2
#define HAS_ARGBTORGB565DITHERROW_AVX2
#define HAS_ARGBTOARGB1555ROW_AVX2
#define HAS_ARGBTOARGB4444ROW_AVX2
#define HAS_I422TORGB565ROW_AVX2
#define HAS_I422TOARGB1555ROW_AVX2
#define HAS_I422TOARGB4444ROW_AVX2
#define HAS_NV12TORGB565ROW_AVX2
#if defined(__x86_64__) || defined(_M_X64)
#define HAS_I422TOAR30ROW_AVX2
#define HAS_RAWTOARGBROW_AVX512BW
@ -4486,6 +4505,42 @@ void I422ToRGBARow_AVX2(const uint8_t* y_buf,
uint8_t* dst_rgba,
const struct YuvConstants* yuvconstants,
int width);
void I422ToRGB565Row_AVX2(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_rgb565,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB1555Row_AVX2(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_argb1555,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB4444Row_AVX2(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_argb4444,
const struct YuvConstants* yuvconstants,
int width);
void I422ToRGB565Row_SSSE3(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_rgb565,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB1555Row_SSSE3(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_argb1555,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB4444Row_SSSE3(const uint8_t* src_y,
const uint8_t* src_u,
const uint8_t* src_v,
uint8_t* dst_argb4444,
const struct YuvConstants* yuvconstants,
int width);
void I444ToARGBRow_SSSE3(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
@ -4694,6 +4749,16 @@ void NV21ToRGB24Row_AVX2(const uint8_t* src_y,
uint8_t* dst_rgb24,
const struct YuvConstants* yuvconstants,
int width);
void NV12ToRGB565Row_SSSE3(const uint8_t* src_y,
const uint8_t* src_uv,
uint8_t* dst_rgb565,
const struct YuvConstants* yuvconstants,
int width);
void NV12ToRGB565Row_AVX2(const uint8_t* src_y,
const uint8_t* src_uv,
uint8_t* dst_rgb565,
const struct YuvConstants* yuvconstants,
int width);
void NV21ToYUV24Row_SSSE3(const uint8_t* src_y,
const uint8_t* src_vu,
uint8_t* dst_yuv24,
@ -5126,6 +5191,52 @@ void I422ToRGB24Row_Any_AVX2(const uint8_t* y_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToRGB565Row_Any_SSSE3(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB1555Row_Any_SSSE3(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB4444Row_Any_SSSE3(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void NV12ToRGB565Row_Any_SSSE3(const uint8_t* y_buf,
const uint8_t* uv_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToRGB565Row_Any_AVX2(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB1555Row_Any_AVX2(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToARGB4444Row_Any_AVX2(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void NV12ToRGB565Row_Any_AVX2(const uint8_t* y_buf,
const uint8_t* uv_buf,
uint8_t* dst_ptr,
const struct YuvConstants* yuvconstants,
int width);
void I422ToRGB24Row_Any_AVX512VBMI(const uint8_t* y_buf,
const uint8_t* u_buf,
const uint8_t* v_buf,

View File

@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1963
#define LIBYUV_VERSION 1964
#endif // INCLUDE_LIBYUV_VERSION_H_

View File

@ -1017,8 +1017,10 @@ ANY11(ARGBToRAWRow_Any_AVX2, ARGBToRAWRow_AVX2, 0, 4, 3, 31)
#if defined(HAS_ARGBTORGB565ROW_AVX2)
ANY11(ARGBToRGB565Row_Any_AVX2, ARGBToRGB565Row_AVX2, 0, 4, 2, 7)
#endif
#if defined(HAS_ARGBTOARGB4444ROW_AVX2)
#if defined(HAS_ARGBTOARGB1555ROW_AVX2)
ANY11(ARGBToARGB1555Row_Any_AVX2, ARGBToARGB1555Row_AVX2, 0, 4, 2, 7)
#endif
#if defined(HAS_ARGBTOARGB4444ROW_AVX2)
ANY11(ARGBToARGB4444Row_Any_AVX2, ARGBToARGB4444Row_AVX2, 0, 4, 2, 7)
#endif
#if defined(HAS_ABGRTOAR30ROW_SSSE3)

View File

@ -4071,7 +4071,7 @@ void I422ToRGB565Row_SSSE3(const uint8_t* src_y,
while (width > 0) {
int twidth = width > MAXTWIDTH ? MAXTWIDTH : width;
I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, yuvconstants, twidth);
ARGBToRGB565Row_SSE2(row, dst_rgb565, twidth);
ARGBToRGB565Row_C(row, dst_rgb565, twidth);
src_y += twidth;
src_u += twidth / 2;
src_v += twidth / 2;
@ -4093,7 +4093,7 @@ void I422ToARGB1555Row_SSSE3(const uint8_t* src_y,
while (width > 0) {
int twidth = width > MAXTWIDTH ? MAXTWIDTH : width;
I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, yuvconstants, twidth);
ARGBToARGB1555Row_SSE2(row, dst_argb1555, twidth);
ARGBToARGB1555Row_C(row, dst_argb1555, twidth);
src_y += twidth;
src_u += twidth / 2;
src_v += twidth / 2;
@ -4115,7 +4115,7 @@ void I422ToARGB4444Row_SSSE3(const uint8_t* src_y,
while (width > 0) {
int twidth = width > MAXTWIDTH ? MAXTWIDTH : width;
I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, yuvconstants, twidth);
ARGBToARGB4444Row_SSE2(row, dst_argb4444, twidth);
ARGBToARGB4444Row_C(row, dst_argb4444, twidth);
src_y += twidth;
src_u += twidth / 2;
src_v += twidth / 2;
@ -4136,7 +4136,7 @@ void NV12ToRGB565Row_SSSE3(const uint8_t* src_y,
while (width > 0) {
int twidth = width > MAXTWIDTH ? MAXTWIDTH : width;
NV12ToARGBRow_SSSE3(src_y, src_uv, row, yuvconstants, twidth);
ARGBToRGB565Row_SSE2(row, dst_rgb565, twidth);
ARGBToRGB565Row_C(row, dst_rgb565, twidth);
src_y += twidth;
src_uv += twidth;
dst_rgb565 += twidth * 2;

View File

@ -921,6 +921,124 @@ void ARGBToRGB565DitherRow_AVX2(const uint8_t* src,
}
#endif // HAS_ARGBTORGB565DITHERROW_AVX2
#ifdef HAS_ARGBTORGB565ROW_AVX2
void ARGBToRGB565Row_AVX2(const uint8_t* src, uint8_t* dst, int width) {
asm volatile(
"vpcmpeqb %%ymm3,%%ymm3,%%ymm3 \n"
"vpsrld $0x1b,%%ymm3,%%ymm3 \n"
"vpcmpeqb %%ymm4,%%ymm4,%%ymm4 \n"
"vpsrld $0x1a,%%ymm4,%%ymm4 \n"
"vpslld $0x5,%%ymm4,%%ymm4 \n"
"vpslld $0xb,%%ymm3,%%ymm5 \n"
LABELALIGN
"1: \n"
"vmovdqu (%0),%%ymm0 \n"
"vpsrld $0x5,%%ymm0,%%ymm2 \n"
"vpsrld $0x3,%%ymm0,%%ymm1 \n"
"vpsrld $0x8,%%ymm0,%%ymm0 \n"
"vpand %%ymm4,%%ymm2,%%ymm2 \n"
"vpand %%ymm3,%%ymm1,%%ymm1 \n"
"vpand %%ymm5,%%ymm0,%%ymm0 \n"
"vpor %%ymm2,%%ymm1,%%ymm1 \n"
"vpor %%ymm1,%%ymm0,%%ymm0 \n"
"vpackusdw %%ymm0,%%ymm0,%%ymm0 \n"
"vpermq $0xd8,%%ymm0,%%ymm0 \n"
"lea 0x20(%0),%0 \n"
"vmovdqu %%xmm0,(%1) \n"
"lea 0x10(%1),%1 \n"
"sub $0x8,%2 \n"
"jg 1b \n"
"vzeroupper \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
:
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
}
#endif // HAS_ARGBTORGB565ROW_AVX2
#ifdef HAS_ARGBTOARGB1555ROW_AVX2
void ARGBToARGB1555Row_AVX2(const uint8_t* src, uint8_t* dst, int width) {
asm volatile(
"vpcmpeqb %%ymm3,%%ymm3,%%ymm3 \n"
"vpslld $0x1f,%%ymm3,%%ymm6 \n"
"vpsrld $0x10,%%ymm6,%%ymm6 \n"
"vpsrld $0x1b,%%ymm3,%%ymm3 \n"
"vpslld $0x5,%%ymm3,%%ymm4 \n"
"vpslld $0xa,%%ymm3,%%ymm5 \n"
LABELALIGN
"1: \n"
"vmovdqu (%0),%%ymm0 \n"
"vpsrld $0x6,%%ymm0,%%ymm2 \n"
"vpsrld $0x3,%%ymm0,%%ymm1 \n"
"vpsrld $0x10,%%ymm0,%%ymm7 \n"
"vpsrld $0x9,%%ymm0,%%ymm0 \n"
"vpand %%ymm4,%%ymm2,%%ymm2 \n"
"vpand %%ymm3,%%ymm1,%%ymm1 \n"
"vpand %%ymm6,%%ymm7,%%ymm7 \n"
"vpand %%ymm5,%%ymm0,%%ymm0 \n"
"vpor %%ymm2,%%ymm1,%%ymm1 \n"
"vpor %%ymm7,%%ymm0,%%ymm0 \n"
"vpor %%ymm1,%%ymm0,%%ymm0 \n"
"vpackusdw %%ymm0,%%ymm0,%%ymm0 \n"
"vpermq $0xd8,%%ymm0,%%ymm0 \n"
"lea 0x20(%0),%0 \n"
"vmovdqu %%xmm0,(%1) \n"
"lea 0x10(%1),%1 \n"
"sub $0x8,%2 \n"
"jg 1b \n"
"vzeroupper \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
:
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
"xmm7");
}
#endif // HAS_ARGBTOARGB1555ROW_AVX2
#ifdef HAS_ARGBTOARGB4444ROW_AVX2
void ARGBToARGB4444Row_AVX2(const uint8_t* src, uint8_t* dst, int width) {
asm volatile(
"vpcmpeqb %%ymm3,%%ymm3,%%ymm3 \n"
"vpsrld $0x1c,%%ymm3,%%ymm3 \n"
"vpslld $0x4,%%ymm3,%%ymm4 \n"
"vpslld $0x8,%%ymm3,%%ymm5 \n"
"vpslld $0xc,%%ymm3,%%ymm6 \n"
LABELALIGN
"1: \n"
"vmovdqu (%0),%%ymm0 \n"
"vpsrld $0x8,%%ymm0,%%ymm2 \n"
"vpsrld $0x4,%%ymm0,%%ymm1 \n"
"vpsrld $0x10,%%ymm0,%%ymm7 \n"
"vpsrld $0xc,%%ymm0,%%ymm0 \n"
"vpand %%ymm4,%%ymm2,%%ymm2 \n"
"vpand %%ymm3,%%ymm1,%%ymm1 \n"
"vpand %%ymm6,%%ymm7,%%ymm7 \n"
"vpand %%ymm5,%%ymm0,%%ymm0 \n"
"vpor %%ymm2,%%ymm1,%%ymm1 \n"
"vpor %%ymm7,%%ymm0,%%ymm0 \n"
"vpor %%ymm1,%%ymm0,%%ymm0 \n"
"vpackusdw %%ymm0,%%ymm0,%%ymm0 \n"
"vpermq $0xd8,%%ymm0,%%ymm0 \n"
"lea 0x20(%0),%0 \n"
"vmovdqu %%xmm0,(%1) \n"
"lea 0x10(%1),%1 \n"
"sub $0x8,%2 \n"
"jg 1b \n"
"vzeroupper \n"
: "+r"(src), // %0
"+r"(dst), // %1
"+r"(width) // %2
:
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",
"xmm7");
}
#endif // HAS_ARGBTOARGB4444ROW_AVX2
#endif // HAS_RGB24TOARGBROW_SSSE3
/*

View File

@ -938,6 +938,140 @@ void ARGB4444ToARGBRow_AVX2(const uint8_t* src_argb4444,
}
#endif
#ifdef HAS_ARGBTORGB565DITHERROW_AVX2
LIBYUV_TARGET_AVX2
void ARGBToRGB565DitherRow_AVX2(const uint8_t* src_argb,
uint8_t* dst_rgb,
uint32_t dither4,
int width) {
__m128i dither_shuf =
_mm_setr_epi8(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3);
__m128i d128 = _mm_shuffle_epi8(_mm_cvtsi32_si128((int)dither4), dither_shuf);
__m256i ymm_dither = _mm256_broadcastsi128_si256(d128);
__m256i mask_b = _mm256_set1_epi32(0x0000001f);
__m256i mask_g = _mm256_set1_epi32(0x000007e0);
__m256i mask_r = _mm256_set1_epi32(0x0000f800);
while (width > 0) {
__m256i ymm0 = _mm256_loadu_si256((const __m256i*)src_argb);
ymm0 = _mm256_adds_epu8(ymm0, ymm_dither);
__m256i ymm2 = _mm256_srli_epi32(ymm0, 5);
__m256i ymm1 = _mm256_srli_epi32(ymm0, 3);
ymm0 = _mm256_srli_epi32(ymm0, 8);
ymm2 = _mm256_and_si256(ymm2, mask_g);
ymm1 = _mm256_and_si256(ymm1, mask_b);
ymm0 = _mm256_and_si256(ymm0, mask_r);
ymm1 = _mm256_or_si256(ymm2, ymm1);
ymm0 = _mm256_or_si256(ymm1, ymm0);
ymm0 = _mm256_packus_epi32(ymm0, ymm0);
ymm0 = _mm256_permute4x64_epi64(ymm0, 0xd8);
_mm_storeu_si128((__m128i*)dst_rgb, _mm256_castsi256_si128(ymm0));
src_argb += 32;
dst_rgb += 16;
width -= 8;
}
_mm256_zeroupper();
}
#endif
#ifdef HAS_ARGBTORGB565ROW_AVX2
LIBYUV_TARGET_AVX2
void ARGBToRGB565Row_AVX2(const uint8_t* src_argb,
uint8_t* dst_rgb,
int width) {
__m256i mask_b = _mm256_set1_epi32(0x0000001f);
__m256i mask_g = _mm256_set1_epi32(0x000007e0);
__m256i mask_r = _mm256_set1_epi32(0x0000f800);
while (width > 0) {
__m256i ymm0 = _mm256_loadu_si256((const __m256i*)src_argb);
__m256i ymm2 = _mm256_srli_epi32(ymm0, 5);
__m256i ymm1 = _mm256_srli_epi32(ymm0, 3);
ymm0 = _mm256_srli_epi32(ymm0, 8);
ymm2 = _mm256_and_si256(ymm2, mask_g);
ymm1 = _mm256_and_si256(ymm1, mask_b);
ymm0 = _mm256_and_si256(ymm0, mask_r);
ymm1 = _mm256_or_si256(ymm2, ymm1);
ymm0 = _mm256_or_si256(ymm1, ymm0);
ymm0 = _mm256_packus_epi32(ymm0, ymm0);
ymm0 = _mm256_permute4x64_epi64(ymm0, 0xd8);
_mm_storeu_si128((__m128i*)dst_rgb, _mm256_castsi256_si128(ymm0));
src_argb += 32;
dst_rgb += 16;
width -= 8;
}
_mm256_zeroupper();
}
#endif
#ifdef HAS_ARGBTOARGB1555ROW_AVX2
LIBYUV_TARGET_AVX2
void ARGBToARGB1555Row_AVX2(const uint8_t* src_argb,
uint8_t* dst_argb1555,
int width) {
__m256i mask_b = _mm256_set1_epi32(0x0000001f);
__m256i mask_g = _mm256_set1_epi32(0x000003e0);
__m256i mask_r = _mm256_set1_epi32(0x00007c00);
__m256i mask_a = _mm256_set1_epi32(0x00008000);
while (width > 0) {
__m256i ymm0 = _mm256_loadu_si256((const __m256i*)src_argb);
__m256i ymm2 = _mm256_srli_epi32(ymm0, 6);
__m256i ymm1 = _mm256_srli_epi32(ymm0, 3);
__m256i ymm7 = _mm256_srli_epi32(ymm0, 16);
ymm0 = _mm256_srli_epi32(ymm0, 9);
ymm2 = _mm256_and_si256(ymm2, mask_g);
ymm1 = _mm256_and_si256(ymm1, mask_b);
ymm7 = _mm256_and_si256(ymm7, mask_a);
ymm0 = _mm256_and_si256(ymm0, mask_r);
ymm1 = _mm256_or_si256(ymm2, ymm1);
ymm0 = _mm256_or_si256(ymm7, ymm0);
ymm0 = _mm256_or_si256(ymm1, ymm0);
ymm0 = _mm256_packus_epi32(ymm0, ymm0);
ymm0 = _mm256_permute4x64_epi64(ymm0, 0xd8);
_mm_storeu_si128((__m128i*)dst_argb1555, _mm256_castsi256_si128(ymm0));
src_argb += 32;
dst_argb1555 += 16;
width -= 8;
}
_mm256_zeroupper();
}
#endif
#ifdef HAS_ARGBTOARGB4444ROW_AVX2
LIBYUV_TARGET_AVX2
void ARGBToARGB4444Row_AVX2(const uint8_t* src_argb,
uint8_t* dst_argb4444,
int width) {
__m256i mask_b = _mm256_set1_epi32(0x0000000f);
__m256i mask_g = _mm256_set1_epi32(0x000000f0);
__m256i mask_r = _mm256_set1_epi32(0x00000f00);
__m256i mask_a = _mm256_set1_epi32(0x0000f000);
while (width > 0) {
__m256i ymm0 = _mm256_loadu_si256((const __m256i*)src_argb);
__m256i ymm2 = _mm256_srli_epi32(ymm0, 8);
__m256i ymm1 = _mm256_srli_epi32(ymm0, 4);
__m256i ymm7 = _mm256_srli_epi32(ymm0, 16);
ymm0 = _mm256_srli_epi32(ymm0, 12);
ymm2 = _mm256_and_si256(ymm2, mask_g);
ymm1 = _mm256_and_si256(ymm1, mask_b);
ymm7 = _mm256_and_si256(ymm7, mask_a);
ymm0 = _mm256_and_si256(ymm0, mask_r);
ymm1 = _mm256_or_si256(ymm2, ymm1);
ymm0 = _mm256_or_si256(ymm7, ymm0);
ymm0 = _mm256_or_si256(ymm1, ymm0);
ymm0 = _mm256_packus_epi32(ymm0, ymm0);
ymm0 = _mm256_permute4x64_epi64(ymm0, 0xd8);
_mm_storeu_si128((__m128i*)dst_argb4444, _mm256_castsi256_si128(ymm0));
src_argb += 32;
dst_argb4444 += 16;
width -= 8;
}
_mm256_zeroupper();
}
#endif
#ifdef HAS_RGB24TOARGBROW_AVX2
LIBYUV_TARGET_AVX2
void RGB24ToARGBRow_AVX2(const uint8_t* src_rgb24,