1391 lines · 44.0 KB · C++
RawDownload
/* *  Copyright 2013 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"#include "libyuv/scale_row.h" #ifdef __cplusplusnamespace libyuv {extern "C" {#endif // This module is for 32 bit Visual C x86 and clangcl#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) // Offsets for source bytes 0 to 9static const uvec8 kShuf0 = {0,   1,   3,   4,   5,   7,   8,   9,                             128, 128, 128, 128, 128, 128, 128, 128}; // Offsets for source bytes 11 to 20 with 8 subtracted = 3 to 12.static const uvec8 kShuf1 = {3,   4,   5,   7,   8,   9,   11,  12,                             128, 128, 128, 128, 128, 128, 128, 128}; // Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31.static const uvec8 kShuf2 = {5,   7,   8,   9,   11,  12,  13,  15,                             128, 128, 128, 128, 128, 128, 128, 128}; // Offsets for source bytes 0 to 10static const uvec8 kShuf01 = {0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10}; // Offsets for source bytes 10 to 21 with 8 subtracted = 3 to 13.static const uvec8 kShuf11 = {2, 3, 4, 5,  5,  6,  6,  7,                              8, 9, 9, 10, 10, 11, 12, 13}; // Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31.static const uvec8 kShuf21 = {5,  6,  6,  7,  8,  9,  9,  10,                              10, 11, 12, 13, 13, 14, 14, 15}; // Coefficients for source bytes 0 to 10static const uvec8 kMadd01 = {3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2}; // Coefficients for source bytes 10 to 21static const uvec8 kMadd11 = {1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1}; // Coefficients for source bytes 21 to 31static const uvec8 kMadd21 = {2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3}; // Coefficients for source bytes 21 to 31static const vec16 kRound34 = {2, 2, 2, 2, 2, 2, 2, 2}; static const uvec8 kShuf38a = {0,   3,   6,   8,   11,  14,  128, 128,                               128, 128, 128, 128, 128, 128, 128, 128}; static const uvec8 kShuf38b = {128, 128, 128, 128, 128, 128, 0,   3,                               6,   8,   11,  14,  128, 128, 128, 128}; // Arrange words 0,3,6 into 0,1,2static const uvec8 kShufAc = {0,   1,   6,   7,   12,  13,  128, 128,                              128, 128, 128, 128, 128, 128, 128, 128}; // Arrange words 0,3,6 into 3,4,5static const uvec8 kShufAc3 = {128, 128, 128, 128, 128, 128, 0,   1,                               6,   7,   12,  13,  128, 128, 128, 128}; // Scaling values for boxes of 3x3 and 2x3static const uvec16 kScaleAc33 = {65536 / 9, 65536 / 9, 65536 / 6, 65536 / 9,                                  65536 / 9, 65536 / 6, 0,         0}; // Arrange first value for pixels 0,1,2,3,4,5static const uvec8 kShufAb0 = {0,  128, 3,  128, 6,   128, 8,   128,                               11, 128, 14, 128, 128, 128, 128, 128}; // Arrange second value for pixels 0,1,2,3,4,5static const uvec8 kShufAb1 = {1,  128, 4,  128, 7,   128, 9,   128,                               12, 128, 15, 128, 128, 128, 128, 128}; // Arrange third value for pixels 0,1,2,3,4,5static const uvec8 kShufAb2 = {2,  128, 5,   128, 128, 128, 10,  128,                               13, 128, 128, 128, 128, 128, 128, 128}; // Scaling values for boxes of 3x2 and 2x2static const uvec16 kScaleAb2 = {65536 / 3, 65536 / 3, 65536 / 2, 65536 / 3,                                 65536 / 3, 65536 / 2, 0,         0}; // Reads 32 pixels, throws half away and writes 16 pixels.__declspec(naked) void ScaleRowDown2_SSSE3(const uint8_t* src_ptr,                                           ptrdiff_t src_stride,                                           uint8_t* dst_ptr,                                           int dst_width) {  __asm {    mov        eax, [esp + 4]  // src_ptr    // src_stride ignored    mov        edx, [esp + 12]  // dst_ptr    mov        ecx, [esp + 16]  // dst_width   wloop:    movdqu     xmm0, [eax]    movdqu     xmm1, [eax + 16]    lea        eax,  [eax + 32]    psrlw      xmm0, 8          // isolate odd pixels.    psrlw      xmm1, 8    packuswb   xmm0, xmm1    movdqu     [edx], xmm0    lea        edx, [edx + 16]    sub        ecx, 16    jg         wloop     ret  }} // Blends 32x1 rectangle to 16x1.__declspec(naked) void ScaleRowDown2Linear_SSSE3(const uint8_t* src_ptr,                                                 ptrdiff_t src_stride,                                                 uint8_t* dst_ptr,                                                 int dst_width) {  __asm {    mov        eax, [esp + 4]  // src_ptr    // src_stride    mov        edx, [esp + 12]  // dst_ptr    mov        ecx, [esp + 16]  // dst_width     pcmpeqb    xmm4, xmm4  // constant 0x0101    psrlw      xmm4, 15    packuswb   xmm4, xmm4    pxor       xmm5, xmm5  // constant 0   wloop:    movdqu     xmm0, [eax]    movdqu     xmm1, [eax + 16]    lea        eax,  [eax + 32]    pmaddubsw  xmm0, xmm4  // horizontal add    pmaddubsw  xmm1, xmm4    pavgw      xmm0, xmm5       // (x + 1) / 2    pavgw      xmm1, xmm5    packuswb   xmm0, xmm1    movdqu     [edx], xmm0    lea        edx, [edx + 16]    sub        ecx, 16    jg         wloop     ret  }} // Blends 32x2 rectangle to 16x1.__declspec(naked) void ScaleRowDown2Box_SSSE3(const uint8_t* src_ptr,                                              ptrdiff_t src_stride,                                              uint8_t* dst_ptr,                                              int dst_width) {  __asm {    push       esi    mov        eax, [esp + 4 + 4]  // src_ptr    mov        esi, [esp + 4 + 8]  // src_stride    mov        edx, [esp + 4 + 12]  // dst_ptr    mov        ecx, [esp + 4 + 16]  // dst_width     pcmpeqb    xmm4, xmm4  // constant 0x0101    psrlw      xmm4, 15    packuswb   xmm4, xmm4    pxor       xmm5, xmm5  // constant 0   wloop:    movdqu     xmm0, [eax]    movdqu     xmm1, [eax + 16]    movdqu     xmm2, [eax + esi]    movdqu     xmm3, [eax + esi + 16]    lea        eax,  [eax + 32]    pmaddubsw  xmm0, xmm4  // horizontal add    pmaddubsw  xmm1, xmm4    pmaddubsw  xmm2, xmm4    pmaddubsw  xmm3, xmm4    paddw      xmm0, xmm2  // vertical add    paddw      xmm1, xmm3    psrlw      xmm0, 1    psrlw      xmm1, 1    pavgw      xmm0, xmm5  // (x + 1) / 2    pavgw      xmm1, xmm5    packuswb   xmm0, xmm1    movdqu     [edx], xmm0    lea        edx, [edx + 16]    sub        ecx, 16    jg         wloop     pop        esi    ret  }} #ifdef HAS_SCALEROWDOWN2_AVX2// Reads 64 pixels, throws half away and writes 32 pixels.__declspec(naked) void ScaleRowDown2_AVX2(const uint8_t* src_ptr,                                          ptrdiff_t src_stride,                                          uint8_t* dst_ptr,                                          int dst_width) {  __asm {    mov        eax, [esp + 4]  // src_ptr    // src_stride ignored    mov        edx, [esp + 12]  // dst_ptr    mov        ecx, [esp + 16]  // dst_width   wloop:    vmovdqu     ymm0, [eax]    vmovdqu     ymm1, [eax + 32]    lea         eax,  [eax + 64]    vpsrlw      ymm0, ymm0, 8  // isolate odd pixels.    vpsrlw      ymm1, ymm1, 8    vpackuswb   ymm0, ymm0, ymm1    vpermq      ymm0, ymm0, 0xd8       // unmutate vpackuswb    vmovdqu     [edx], ymm0    lea         edx, [edx + 32]    sub         ecx, 32    jg          wloop     vzeroupper    ret  }} // Blends 64x1 rectangle to 32x1.__declspec(naked) void ScaleRowDown2Linear_AVX2(const uint8_t* src_ptr,                                                ptrdiff_t src_stride,                                                uint8_t* dst_ptr,                                                int dst_width) {  __asm {    mov         eax, [esp + 4]  // src_ptr    // src_stride    mov         edx, [esp + 12]  // dst_ptr    mov         ecx, [esp + 16]  // dst_width     vpcmpeqb    ymm4, ymm4, ymm4  // '1' constant, 8b    vpsrlw      ymm4, ymm4, 15    vpackuswb   ymm4, ymm4, ymm4    vpxor       ymm5, ymm5, ymm5  // constant 0   wloop:    vmovdqu     ymm0, [eax]    vmovdqu     ymm1, [eax + 32]    lea         eax,  [eax + 64]    vpmaddubsw  ymm0, ymm0, ymm4  // horizontal add    vpmaddubsw  ymm1, ymm1, ymm4    vpavgw      ymm0, ymm0, ymm5  // (x + 1) / 2    vpavgw      ymm1, ymm1, ymm5    vpackuswb   ymm0, ymm0, ymm1    vpermq      ymm0, ymm0, 0xd8       // unmutate vpackuswb    vmovdqu     [edx], ymm0    lea         edx, [edx + 32]    sub         ecx, 32    jg          wloop     vzeroupper    ret  }} // For rounding, average = (sum + 2) / 4// becomes average((sum >> 1), 0)// Blends 64x2 rectangle to 32x1.__declspec(naked) void ScaleRowDown2Box_AVX2(const uint8_t* src_ptr,                                             ptrdiff_t src_stride,                                             uint8_t* dst_ptr,                                             int dst_width) {  __asm {    push        esi    mov         eax, [esp + 4 + 4]  // src_ptr    mov         esi, [esp + 4 + 8]  // src_stride    mov         edx, [esp + 4 + 12]  // dst_ptr    mov         ecx, [esp + 4 + 16]  // dst_width     vpcmpeqb    ymm4, ymm4, ymm4  // '1' constant, 8b    vpsrlw      ymm4, ymm4, 15    vpackuswb   ymm4, ymm4, ymm4    vpxor       ymm5, ymm5, ymm5  // constant 0   wloop:    vmovdqu     ymm0, [eax]    vmovdqu     ymm1, [eax + 32]    vmovdqu     ymm2, [eax + esi]    vmovdqu     ymm3, [eax + esi + 32]    lea         eax,  [eax + 64]    vpmaddubsw  ymm0, ymm0, ymm4  // horizontal add    vpmaddubsw  ymm1, ymm1, ymm4    vpmaddubsw  ymm2, ymm2, ymm4    vpmaddubsw  ymm3, ymm3, ymm4    vpaddw      ymm0, ymm0, ymm2  // vertical add    vpaddw      ymm1, ymm1, ymm3    vpsrlw      ymm0, ymm0, 1  // (x + 2) / 4 = (x / 2 + 1) / 2    vpsrlw      ymm1, ymm1, 1    vpavgw      ymm0, ymm0, ymm5  // (x + 1) / 2    vpavgw      ymm1, ymm1, ymm5    vpackuswb   ymm0, ymm0, ymm1    vpermq      ymm0, ymm0, 0xd8  // unmutate vpackuswb    vmovdqu     [edx], ymm0    lea         edx, [edx + 32]    sub         ecx, 32    jg          wloop     pop         esi    vzeroupper    ret  }}#endif  // HAS_SCALEROWDOWN2_AVX2 // Point samples 32 pixels to 8 pixels.__declspec(naked) void ScaleRowDown4_SSSE3(const uint8_t* src_ptr,                                           ptrdiff_t src_stride,                                           uint8_t* dst_ptr,                                           int dst_width) {  __asm {    mov        eax, [esp + 4]  // src_ptr    // src_stride ignored    mov        edx, [esp + 12]  // dst_ptr    mov        ecx, [esp + 16]  // dst_width    pcmpeqb    xmm5, xmm5       // generate mask 0x00ff0000    psrld      xmm5, 24    pslld      xmm5, 16   wloop:    movdqu     xmm0, [eax]    movdqu     xmm1, [eax + 16]    lea        eax,  [eax + 32]    pand       xmm0, xmm5    pand       xmm1, xmm5    packuswb   xmm0, xmm1    psrlw      xmm0, 8    packuswb   xmm0, xmm0    movq       qword ptr [edx], xmm0    lea        edx, [edx + 8]    sub        ecx, 8    jg         wloop     ret  }} // Blends 32x4 rectangle to 8x1.__declspec(naked) void ScaleRowDown4Box_SSSE3(const uint8_t* src_ptr,                                              ptrdiff_t src_stride,                                              uint8_t* dst_ptr,                                              int dst_width) {  __asm {    push       esi    push       edi    mov        eax, [esp + 8 + 4]  // src_ptr    mov        esi, [esp + 8 + 8]  // src_stride    mov        edx, [esp + 8 + 12]  // dst_ptr    mov        ecx, [esp + 8 + 16]  // dst_width    lea        edi, [esi + esi * 2]  // src_stride * 3    pcmpeqb    xmm4, xmm4  // constant 0x0101    psrlw      xmm4, 15    movdqa     xmm5, xmm4    packuswb   xmm4, xmm4    psllw      xmm5, 3  // constant 0x0008   wloop:    movdqu     xmm0, [eax]  // average rows    movdqu     xmm1, [eax + 16]    movdqu     xmm2, [eax + esi]    movdqu     xmm3, [eax + esi + 16]    pmaddubsw  xmm0, xmm4  // horizontal add    pmaddubsw  xmm1, xmm4    pmaddubsw  xmm2, xmm4    pmaddubsw  xmm3, xmm4    paddw      xmm0, xmm2  // vertical add rows 0, 1    paddw      xmm1, xmm3    movdqu     xmm2, [eax + esi * 2]    movdqu     xmm3, [eax + esi * 2 + 16]    pmaddubsw  xmm2, xmm4    pmaddubsw  xmm3, xmm4    paddw      xmm0, xmm2  // add row 2    paddw      xmm1, xmm3    movdqu     xmm2, [eax + edi]    movdqu     xmm3, [eax + edi + 16]    lea        eax, [eax + 32]    pmaddubsw  xmm2, xmm4    pmaddubsw  xmm3, xmm4    paddw      xmm0, xmm2  // add row 3    paddw      xmm1, xmm3    phaddw     xmm0, xmm1    paddw      xmm0, xmm5  // + 8 for round    psrlw      xmm0, 4  // /16 for average of 4 * 4    packuswb   xmm0, xmm0    movq       qword ptr [edx], xmm0    lea        edx, [edx + 8]    sub        ecx, 8    jg         wloop     pop        edi    pop        esi    ret  }} #ifdef HAS_SCALEROWDOWN4_AVX2// Point samples 64 pixels to 16 pixels.__declspec(naked) void ScaleRowDown4_AVX2(const uint8_t* src_ptr,                                          ptrdiff_t src_stride,                                          uint8_t* dst_ptr,                                          int dst_width) {  __asm {    mov         eax, [esp + 4]  // src_ptr    // src_stride ignored    mov         edx, [esp + 12]  // dst_ptr    mov         ecx, [esp + 16]  // dst_width    vpcmpeqb    ymm5, ymm5, ymm5  // generate mask 0x00ff0000    vpsrld      ymm5, ymm5, 24    vpslld      ymm5, ymm5, 16   wloop:    vmovdqu     ymm0, [eax]    vmovdqu     ymm1, [eax + 32]    lea         eax,  [eax + 64]    vpand       ymm0, ymm0, ymm5    vpand       ymm1, ymm1, ymm5    vpackuswb   ymm0, ymm0, ymm1    vpermq      ymm0, ymm0, 0xd8  // unmutate vpackuswb    vpsrlw      ymm0, ymm0, 8    vpackuswb   ymm0, ymm0, ymm0    vpermq      ymm0, ymm0, 0xd8       // unmutate vpackuswb    vmovdqu     [edx], xmm0    lea         edx, [edx + 16]    sub         ecx, 16    jg          wloop     vzeroupper    ret  }} // Blends 64x4 rectangle to 16x1.__declspec(naked) void ScaleRowDown4Box_AVX2(const uint8_t* src_ptr,                                             ptrdiff_t src_stride,                                             uint8_t* dst_ptr,                                             int dst_width) {  __asm {    push        esi    push        edi    mov         eax, [esp + 8 + 4]  // src_ptr    mov         esi, [esp + 8 + 8]  // src_stride    mov         edx, [esp + 8 + 12]  // dst_ptr    mov         ecx, [esp + 8 + 16]  // dst_width    lea         edi, [esi + esi * 2]  // src_stride * 3    vpcmpeqb    ymm4, ymm4, ymm4  // constant 0x0101    vpsrlw      ymm4, ymm4, 15    vpsllw      ymm5, ymm4, 3  // constant 0x0008    vpackuswb   ymm4, ymm4, ymm4   wloop:    vmovdqu     ymm0, [eax]  // average rows    vmovdqu     ymm1, [eax + 32]    vmovdqu     ymm2, [eax + esi]    vmovdqu     ymm3, [eax + esi + 32]    vpmaddubsw  ymm0, ymm0, ymm4  // horizontal add    vpmaddubsw  ymm1, ymm1, ymm4    vpmaddubsw  ymm2, ymm2, ymm4    vpmaddubsw  ymm3, ymm3, ymm4    vpaddw      ymm0, ymm0, ymm2  // vertical add rows 0, 1    vpaddw      ymm1, ymm1, ymm3    vmovdqu     ymm2, [eax + esi * 2]    vmovdqu     ymm3, [eax + esi * 2 + 32]    vpmaddubsw  ymm2, ymm2, ymm4    vpmaddubsw  ymm3, ymm3, ymm4    vpaddw      ymm0, ymm0, ymm2  // add row 2    vpaddw      ymm1, ymm1, ymm3    vmovdqu     ymm2, [eax + edi]    vmovdqu     ymm3, [eax + edi + 32]    lea         eax,  [eax + 64]    vpmaddubsw  ymm2, ymm2, ymm4    vpmaddubsw  ymm3, ymm3, ymm4    vpaddw      ymm0, ymm0, ymm2  // add row 3    vpaddw      ymm1, ymm1, ymm3    vphaddw     ymm0, ymm0, ymm1  // mutates    vpermq      ymm0, ymm0, 0xd8  // unmutate vphaddw    vpaddw      ymm0, ymm0, ymm5  // + 8 for round    vpsrlw      ymm0, ymm0, 4  // /32 for average of 4 * 4    vpackuswb   ymm0, ymm0, ymm0    vpermq      ymm0, ymm0, 0xd8  // unmutate vpackuswb    vmovdqu     [edx], xmm0    lea         edx, [edx + 16]    sub         ecx, 16    jg          wloop     pop        edi    pop        esi    vzeroupper    ret  }}#endif  // HAS_SCALEROWDOWN4_AVX2 // Point samples 32 pixels to 24 pixels.// Produces three 8 byte values. For each 8 bytes, 16 bytes are read.// Then shuffled to do the scaling.

Lines 1–500 of 1391.

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