6234 lines · 201.8 KB · C++
RawDownload
/* *  Copyright 2011 The LibYuv Project Authors. All rights reserved. * *  Use of this source code is governed by a BSD-style license *  that can be found in the LICENSE file in the root of the source *  tree. An additional intellectual property rights grant can be found *  in the file PATENTS. All contributing project authors may *  be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/row.h" // This module is for Visual C 32/64 bit and clangcl 32 bit#if !defined(LIBYUV_DISABLE_X86) && defined(_MSC_VER) && \    (defined(_M_IX86) || (defined(_M_X64) && !defined(__clang__))) #if defined(_M_X64)#include <emmintrin.h>#include <tmmintrin.h>  // For _mm_maddubs_epi16#endif #ifdef __cplusplusnamespace libyuv {extern "C" {#endif // 64 bit#if defined(_M_X64) // Read 4 UV from 422, upsample to 8 UV.#define READYUV422                                        \  xmm0 = _mm_cvtsi32_si128(*(uint32_t*)u_buf);            \  xmm1 = _mm_cvtsi32_si128(*(uint32_t*)(u_buf + offset)); \  xmm0 = _mm_unpacklo_epi8(xmm0, xmm1);                   \  xmm0 = _mm_unpacklo_epi16(xmm0, xmm0);                  \  u_buf += 4;                                             \  xmm4 = _mm_loadl_epi64((__m128i*)y_buf);                \  xmm4 = _mm_unpacklo_epi8(xmm4, xmm4);                   \  y_buf += 8; // Read 4 UV from 422, upsample to 8 UV.  With 8 Alpha.#define READYUVA422                                       \  xmm0 = _mm_cvtsi32_si128(*(uint32_t*)u_buf);            \  xmm1 = _mm_cvtsi32_si128(*(uint32_t*)(u_buf + offset)); \  xmm0 = _mm_unpacklo_epi8(xmm0, xmm1);                   \  xmm0 = _mm_unpacklo_epi16(xmm0, xmm0);                  \  u_buf += 4;                                             \  xmm4 = _mm_loadl_epi64((__m128i*)y_buf);                \  xmm4 = _mm_unpacklo_epi8(xmm4, xmm4);                   \  y_buf += 8;                                             \  xmm5 = _mm_loadl_epi64((__m128i*)a_buf);                \  a_buf += 8; // Convert 8 pixels: 8 UV and 8 Y.#define YUVTORGB(yuvconstants)                                     \  xmm1 = _mm_loadu_si128(&xmm0);                                   \  xmm2 = _mm_loadu_si128(&xmm0);                                   \  xmm0 = _mm_maddubs_epi16(xmm0, *(__m128i*)yuvconstants->kUVToB); \  xmm1 = _mm_maddubs_epi16(xmm1, *(__m128i*)yuvconstants->kUVToG); \  xmm2 = _mm_maddubs_epi16(xmm2, *(__m128i*)yuvconstants->kUVToR); \  xmm0 = _mm_sub_epi16(*(__m128i*)yuvconstants->kUVBiasB, xmm0);   \  xmm1 = _mm_sub_epi16(*(__m128i*)yuvconstants->kUVBiasG, xmm1);   \  xmm2 = _mm_sub_epi16(*(__m128i*)yuvconstants->kUVBiasR, xmm2);   \  xmm4 = _mm_mulhi_epu16(xmm4, *(__m128i*)yuvconstants->kYToRgb);  \  xmm0 = _mm_adds_epi16(xmm0, xmm4);                               \  xmm1 = _mm_adds_epi16(xmm1, xmm4);                               \  xmm2 = _mm_adds_epi16(xmm2, xmm4);                               \  xmm0 = _mm_srai_epi16(xmm0, 6);                                  \  xmm1 = _mm_srai_epi16(xmm1, 6);                                  \  xmm2 = _mm_srai_epi16(xmm2, 6);                                  \  xmm0 = _mm_packus_epi16(xmm0, xmm0);                             \  xmm1 = _mm_packus_epi16(xmm1, xmm1);                             \  xmm2 = _mm_packus_epi16(xmm2, xmm2); // Store 8 ARGB values.#define STOREARGB                                    \  xmm0 = _mm_unpacklo_epi8(xmm0, xmm1);              \  xmm2 = _mm_unpacklo_epi8(xmm2, xmm5);              \  xmm1 = _mm_loadu_si128(&xmm0);                     \  xmm0 = _mm_unpacklo_epi16(xmm0, xmm2);             \  xmm1 = _mm_unpackhi_epi16(xmm1, xmm2);             \  _mm_storeu_si128((__m128i*)dst_argb, xmm0);        \  _mm_storeu_si128((__m128i*)(dst_argb + 16), xmm1); \  dst_argb += 32; #if defined(HAS_I422TOARGBROW_SSSE3)void I422ToARGBRow_SSSE3(const uint8_t* y_buf,                         const uint8_t* u_buf,                         const uint8_t* v_buf,                         uint8_t* dst_argb,                         const struct YuvConstants* yuvconstants,                         int width) {  __m128i xmm0, xmm1, xmm2, xmm4;  const __m128i xmm5 = _mm_set1_epi8(-1);  const ptrdiff_t offset = (uint8_t*)v_buf - (uint8_t*)u_buf;  while (width > 0) {    READYUV422    YUVTORGB(yuvconstants)    STOREARGB    width -= 8;  }}#endif #if defined(HAS_I422ALPHATOARGBROW_SSSE3)void I422AlphaToARGBRow_SSSE3(const uint8_t* y_buf,                              const uint8_t* u_buf,                              const uint8_t* v_buf,                              const uint8_t* a_buf,                              uint8_t* dst_argb,                              const struct YuvConstants* yuvconstants,                              int width) {  __m128i xmm0, xmm1, xmm2, xmm4, xmm5;  const ptrdiff_t offset = (uint8_t*)v_buf - (uint8_t*)u_buf;  while (width > 0) {    READYUVA422    YUVTORGB(yuvconstants)    STOREARGB    width -= 8;  }}#endif // 32 bit#else  // defined(_M_X64)#ifdef HAS_ARGBTOYROW_SSSE3 // Constants for ARGB.static const vec8 kARGBToY = {13, 65, 33, 0, 13, 65, 33, 0,                              13, 65, 33, 0, 13, 65, 33, 0}; // JPeg full range.static const vec8 kARGBToYJ = {15, 75, 38, 0, 15, 75, 38, 0,                               15, 75, 38, 0, 15, 75, 38, 0}; static const vec8 kARGBToU = {112, -74, -38, 0, 112, -74, -38, 0,                              112, -74, -38, 0, 112, -74, -38, 0}; static const vec8 kARGBToUJ = {127, -84, -43, 0, 127, -84, -43, 0,                               127, -84, -43, 0, 127, -84, -43, 0}; static const vec8 kARGBToV = {    -18, -94, 112, 0, -18, -94, 112, 0, -18, -94, 112, 0, -18, -94, 112, 0,}; static const vec8 kARGBToVJ = {-20, -107, 127, 0, -20, -107, 127, 0,                               -20, -107, 127, 0, -20, -107, 127, 0}; // vpshufb for vphaddw + vpackuswb packed to shorts.static const lvec8 kShufARGBToUV_AVX = {    0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15,    0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15}; // Constants for BGRA.static const vec8 kBGRAToY = {0, 33, 65, 13, 0, 33, 65, 13,                              0, 33, 65, 13, 0, 33, 65, 13}; static const vec8 kBGRAToU = {0, -38, -74, 112, 0, -38, -74, 112,                              0, -38, -74, 112, 0, -38, -74, 112}; static const vec8 kBGRAToV = {0, 112, -94, -18, 0, 112, -94, -18,                              0, 112, -94, -18, 0, 112, -94, -18}; // Constants for ABGR.static const vec8 kABGRToY = {33, 65, 13, 0, 33, 65, 13, 0,                              33, 65, 13, 0, 33, 65, 13, 0}; static const vec8 kABGRToU = {-38, -74, 112, 0, -38, -74, 112, 0,                              -38, -74, 112, 0, -38, -74, 112, 0}; static const vec8 kABGRToV = {112, -94, -18, 0, 112, -94, -18, 0,                              112, -94, -18, 0, 112, -94, -18, 0}; // Constants for RGBA.static const vec8 kRGBAToY = {0, 13, 65, 33, 0, 13, 65, 33,                              0, 13, 65, 33, 0, 13, 65, 33}; static const vec8 kRGBAToU = {0, 112, -74, -38, 0, 112, -74, -38,                              0, 112, -74, -38, 0, 112, -74, -38}; static const vec8 kRGBAToV = {0, -18, -94, 112, 0, -18, -94, 112,                              0, -18, -94, 112, 0, -18, -94, 112}; static const uvec8 kAddY16 = {16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u,                              16u, 16u, 16u, 16u, 16u, 16u, 16u, 16u}; // 7 bit fixed point 0.5.static const vec16 kAddYJ64 = {64, 64, 64, 64, 64, 64, 64, 64}; static const uvec8 kAddUV128 = {128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u,                                128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u}; static const uvec16 kAddUVJ128 = {0x8080u, 0x8080u, 0x8080u, 0x8080u,                                  0x8080u, 0x8080u, 0x8080u, 0x8080u}; // Shuffle table for converting RGB24 to ARGB.static const uvec8 kShuffleMaskRGB24ToARGB = {    0u, 1u, 2u, 12u, 3u, 4u, 5u, 13u, 6u, 7u, 8u, 14u, 9u, 10u, 11u, 15u}; // Shuffle table for converting RAW to ARGB.static const uvec8 kShuffleMaskRAWToARGB = {2u, 1u, 0u, 12u, 5u,  4u,  3u, 13u,                                            8u, 7u, 6u, 14u, 11u, 10u, 9u, 15u}; // Shuffle table for converting RAW to RGB24.  First 8.static const uvec8 kShuffleMaskRAWToRGB24_0 = {    2u,   1u,   0u,   5u,   4u,   3u,   8u,   7u,    128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u}; // Shuffle table for converting RAW to RGB24.  Middle 8.static const uvec8 kShuffleMaskRAWToRGB24_1 = {    2u,   7u,   6u,   5u,   10u,  9u,   8u,   13u,    128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u}; // Shuffle table for converting RAW to RGB24.  Last 8.static const uvec8 kShuffleMaskRAWToRGB24_2 = {    8u,   7u,   12u,  11u,  10u,  15u,  14u,  13u,    128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u}; // Shuffle table for converting ARGB to RGB24.static const uvec8 kShuffleMaskARGBToRGB24 = {    0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 10u, 12u, 13u, 14u, 128u, 128u, 128u, 128u}; // Shuffle table for converting ARGB to RAW.static const uvec8 kShuffleMaskARGBToRAW = {    2u, 1u, 0u, 6u, 5u, 4u, 10u, 9u, 8u, 14u, 13u, 12u, 128u, 128u, 128u, 128u}; // Shuffle table for converting ARGBToRGB24 for I422ToRGB24.  First 8 + next 4static const uvec8 kShuffleMaskARGBToRGB24_0 = {    0u, 1u, 2u, 4u, 5u, 6u, 8u, 9u, 128u, 128u, 128u, 128u, 10u, 12u, 13u, 14u}; // YUY2 shuf 16 Y to 32 Y.static const lvec8 kShuffleYUY2Y = {0,  0,  2,  2,  4,  4,  6,  6,  8,  8, 10,                                    10, 12, 12, 14, 14, 0,  0,  2,  2,  4, 4,                                    6,  6,  8,  8,  10, 10, 12, 12, 14, 14}; // YUY2 shuf 8 UV to 16 UV.static const lvec8 kShuffleYUY2UV = {1,  3,  1,  3,  5,  7,  5,  7,  9,  11, 9,                                     11, 13, 15, 13, 15, 1,  3,  1,  3,  5,  7,                                     5,  7,  9,  11, 9,  11, 13, 15, 13, 15}; // UYVY shuf 16 Y to 32 Y.static const lvec8 kShuffleUYVYY = {1,  1,  3,  3,  5,  5,  7,  7,  9,  9, 11,                                    11, 13, 13, 15, 15, 1,  1,  3,  3,  5, 5,                                    7,  7,  9,  9,  11, 11, 13, 13, 15, 15}; // UYVY shuf 8 UV to 16 UV.static const lvec8 kShuffleUYVYUV = {0,  2,  0,  2,  4,  6,  4,  6,  8,  10, 8,                                     10, 12, 14, 12, 14, 0,  2,  0,  2,  4,  6,                                     4,  6,  8,  10, 8,  10, 12, 14, 12, 14}; // NV21 shuf 8 VU to 16 UV.static const lvec8 kShuffleNV21 = {    1, 0, 1, 0, 3, 2, 3, 2, 5, 4, 5, 4, 7, 6, 7, 6,    1, 0, 1, 0, 3, 2, 3, 2, 5, 4, 5, 4, 7, 6, 7, 6,}; // Duplicates gray value 3 times and fills in alpha opaque.__declspec(naked) void J400ToARGBRow_SSE2(const uint8_t* src_y,                                          uint8_t* dst_argb,                                          int width) {  __asm {    mov        eax, [esp + 4]  // src_y    mov        edx, [esp + 8]  // dst_argb    mov        ecx, [esp + 12]  // width    pcmpeqb    xmm5, xmm5  // generate mask 0xff000000    pslld      xmm5, 24   convertloop:    movq       xmm0, qword ptr [eax]    lea        eax,  [eax + 8]    punpcklbw  xmm0, xmm0    movdqa     xmm1, xmm0    punpcklwd  xmm0, xmm0    punpckhwd  xmm1, xmm1    por        xmm0, xmm5    por        xmm1, xmm5    movdqu     [edx], xmm0    movdqu     [edx + 16], xmm1    lea        edx, [edx + 32]    sub        ecx, 8    jg         convertloop    ret  }} #ifdef HAS_J400TOARGBROW_AVX2// Duplicates gray value 3 times and fills in alpha opaque.__declspec(naked) void J400ToARGBRow_AVX2(const uint8_t* src_y,                                          uint8_t* dst_argb,                                          int width) {  __asm {    mov         eax, [esp + 4]  // src_y    mov         edx, [esp + 8]  // dst_argb    mov         ecx, [esp + 12]  // width    vpcmpeqb    ymm5, ymm5, ymm5  // generate mask 0xff000000    vpslld      ymm5, ymm5, 24   convertloop:    vmovdqu     xmm0, [eax]    lea         eax,  [eax + 16]    vpermq      ymm0, ymm0, 0xd8    vpunpcklbw  ymm0, ymm0, ymm0    vpermq      ymm0, ymm0, 0xd8    vpunpckhwd  ymm1, ymm0, ymm0    vpunpcklwd  ymm0, ymm0, ymm0    vpor        ymm0, ymm0, ymm5    vpor        ymm1, ymm1, ymm5    vmovdqu     [edx], ymm0    vmovdqu     [edx + 32], ymm1    lea         edx, [edx + 64]    sub         ecx, 16    jg          convertloop    vzeroupper    ret  }}#endif  // HAS_J400TOARGBROW_AVX2 __declspec(naked) void RGB24ToARGBRow_SSSE3(const uint8_t* src_rgb24,                                            uint8_t* dst_argb,                                            int width) {  __asm {    mov       eax, [esp + 4]  // src_rgb24    mov       edx, [esp + 8]  // dst_argb    mov       ecx, [esp + 12]  // width    pcmpeqb   xmm5, xmm5  // generate mask 0xff000000    pslld     xmm5, 24    movdqa    xmm4, xmmword ptr kShuffleMaskRGB24ToARGB  convertloop:    movdqu    xmm0, [eax]    movdqu    xmm1, [eax + 16]    movdqu    xmm3, [eax + 32]    lea       eax, [eax + 48]    movdqa    xmm2, xmm3    palignr   xmm2, xmm1, 8  // xmm2 = { xmm3[0:3] xmm1[8:15]}    pshufb    xmm2, xmm4    por       xmm2, xmm5    palignr   xmm1, xmm0, 12  // xmm1 = { xmm3[0:7] xmm0[12:15]}    pshufb    xmm0, xmm4    movdqu    [edx + 32], xmm2    por       xmm0, xmm5    pshufb    xmm1, xmm4    movdqu    [edx], xmm0    por       xmm1, xmm5    palignr   xmm3, xmm3, 4  // xmm3 = { xmm3[4:15]}    pshufb    xmm3, xmm4    movdqu    [edx + 16], xmm1    por       xmm3, xmm5    movdqu    [edx + 48], xmm3    lea       edx, [edx + 64]    sub       ecx, 16    jg        convertloop    ret  }} __declspec(naked) void RAWToARGBRow_SSSE3(const uint8_t* src_raw,                                          uint8_t* dst_argb,                                          int width) {  __asm {    mov       eax, [esp + 4]  // src_raw    mov       edx, [esp + 8]  // dst_argb    mov       ecx, [esp + 12]  // width    pcmpeqb   xmm5, xmm5  // generate mask 0xff000000    pslld     xmm5, 24    movdqa    xmm4, xmmword ptr kShuffleMaskRAWToARGB  convertloop:    movdqu    xmm0, [eax]    movdqu    xmm1, [eax + 16]    movdqu    xmm3, [eax + 32]    lea       eax, [eax + 48]    movdqa    xmm2, xmm3    palignr   xmm2, xmm1, 8  // xmm2 = { xmm3[0:3] xmm1[8:15]}    pshufb    xmm2, xmm4    por       xmm2, xmm5    palignr   xmm1, xmm0, 12  // xmm1 = { xmm3[0:7] xmm0[12:15]}    pshufb    xmm0, xmm4    movdqu    [edx + 32], xmm2    por       xmm0, xmm5    pshufb    xmm1, xmm4    movdqu    [edx], xmm0    por       xmm1, xmm5    palignr   xmm3, xmm3, 4  // xmm3 = { xmm3[4:15]}    pshufb    xmm3, xmm4    movdqu    [edx + 16], xmm1    por       xmm3, xmm5    movdqu    [edx + 48], xmm3    lea       edx, [edx + 64]    sub       ecx, 16    jg        convertloop    ret  }} __declspec(naked) void RAWToRGB24Row_SSSE3(const uint8_t* src_raw,                                           uint8_t* dst_rgb24,                                           int width) {  __asm {    mov       eax, [esp + 4]  // src_raw    mov       edx, [esp + 8]  // dst_rgb24    mov       ecx, [esp + 12]  // width    movdqa    xmm3, xmmword ptr kShuffleMaskRAWToRGB24_0    movdqa    xmm4, xmmword ptr kShuffleMaskRAWToRGB24_1    movdqa    xmm5, xmmword ptr kShuffleMaskRAWToRGB24_2  convertloop:    movdqu    xmm0, [eax]    movdqu    xmm1, [eax + 4]    movdqu    xmm2, [eax + 8]    lea       eax, [eax + 24]    pshufb    xmm0, xmm3    pshufb    xmm1, xmm4    pshufb    xmm2, xmm5    movq      qword ptr [edx], xmm0    movq      qword ptr [edx + 8], xmm1    movq      qword ptr [edx + 16], xmm2    lea       edx, [edx + 24]    sub       ecx, 8    jg        convertloop    ret  }} // pmul method to replicate bits.// Math to replicate bits:// (v << 8) | (v << 3)// v * 256 + v * 8// v * (256 + 8)// G shift of 5 is incorporated, so shift is 5 + 8 and 5 + 3// 20 instructions.__declspec(naked) void RGB565ToARGBRow_SSE2(const uint8_t* src_rgb565,                                            uint8_t* dst_argb,                                            int width) {  __asm {    mov       eax, 0x01080108  // generate multiplier to repeat 5 bits    movd      xmm5, eax    pshufd    xmm5, xmm5, 0    mov       eax, 0x20802080  // multiplier shift by 5 and then repeat 6 bits    movd      xmm6, eax    pshufd    xmm6, xmm6, 0    pcmpeqb   xmm3, xmm3  // generate mask 0xf800f800 for Red    psllw     xmm3, 11    pcmpeqb   xmm4, xmm4  // generate mask 0x07e007e0 for Green    psllw     xmm4, 10    psrlw     xmm4, 5    pcmpeqb   xmm7, xmm7  // generate mask 0xff00ff00 for Alpha    psllw     xmm7, 8     mov       eax, [esp + 4]  // src_rgb565    mov       edx, [esp + 8]  // dst_argb    mov       ecx, [esp + 12]  // width    sub       edx, eax    sub       edx, eax  convertloop:    movdqu    xmm0, [eax]  // fetch 8 pixels of bgr565    movdqa    xmm1, xmm0    movdqa    xmm2, xmm0    pand      xmm1, xmm3  // R in upper 5 bits    psllw     xmm2, 11  // B in upper 5 bits    pmulhuw   xmm1, xmm5  // * (256 + 8)    pmulhuw   xmm2, xmm5  // * (256 + 8)    psllw     xmm1, 8    por       xmm1, xmm2  // RB    pand      xmm0, xmm4  // G in middle 6 bits    pmulhuw   xmm0, xmm6  // << 5 * (256 + 4)    por       xmm0, xmm7  // AG    movdqa    xmm2, xmm1    punpcklbw xmm1, xmm0    punpckhbw xmm2, xmm0    movdqu    [eax * 2 + edx], xmm1  // store 4 pixels of ARGB    movdqu    [eax * 2 + edx + 16], xmm2  // store next 4 pixels of ARGB    lea       eax, [eax + 16]    sub       ecx, 8    jg        convertloop    ret  }} #ifdef HAS_RGB565TOARGBROW_AVX2// pmul method to replicate bits.// Math to replicate bits:// (v << 8) | (v << 3)// v * 256 + v * 8// v * (256 + 8)// G shift of 5 is incorporated, so shift is 5 + 8 and 5 + 3__declspec(naked) void RGB565ToARGBRow_AVX2(const uint8_t* src_rgb565,                                            uint8_t* dst_argb,                                            int width) {  __asm {    mov        eax, 0x01080108  // generate multiplier to repeat 5 bits    vmovd      xmm5, eax    vbroadcastss ymm5, xmm5    mov        eax, 0x20802080  // multiplier shift by 5 and then repeat 6 bits    vmovd      xmm6, eax    vbroadcastss ymm6, xmm6    vpcmpeqb   ymm3, ymm3, ymm3  // generate mask 0xf800f800 for Red    vpsllw     ymm3, ymm3, 11

Lines 1–500 of 6234.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t