| Index: media/base/simd/convert_yuv_to_rgb_ssse3.asm
|
| ===================================================================
|
| --- media/base/simd/convert_yuv_to_rgb_ssse3.asm (revision 0)
|
| +++ media/base/simd/convert_yuv_to_rgb_ssse3.asm (revision 0)
|
| @@ -0,0 +1,336 @@
|
| +; Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +; Use of this source code is governed by a BSD-style license that can be
|
| +; found in the LICENSE file.
|
| +
|
| +%include "x86inc.asm"
|
| +
|
| +;
|
| +; A table used in this file.
|
| +; static const int16 kSIMD_ConvertYUVtoARGB_kTable[] = {
|
| +; -16, -128, -128, 128,
|
| +; 298, 0, 409, 1,
|
| +; 298, -100, -208, 1,
|
| +; 298, 516, 0, 1,
|
| +; };
|
| +;
|
| + SECTION_RODATA
|
| +
|
| +SIMD_ConvertYUVtoARGB_kTable:
|
| + dw -16, -128, -128, 128
|
| + dw 298, 0, 409, 1
|
| + dw 298, -100, -208, 1
|
| + dw 298, 516, 0, 1,
|
| +
|
| +;
|
| +; This file uses SSE, SSE2, SSE3, and SSSE3, which are supported by all ATOM
|
| +; processors.
|
| +;
|
| + SECTION_TEXT
|
| + CPU SSE, SSE2, SSE3, SSSE3
|
| +
|
| +;
|
| +; XMM registers representing constants. We must not use these registers as
|
| +; destination operands.
|
| +; for (int i = 0; i < 8; i += 4) {
|
| +; xmm7.w[i] = -16; xmm7.w[i+1] = -128; xmm7.w[i+2] = -128; xmm7.w[i+3] = 128;
|
| +; xmm6.w[i] = 298; xmm6.w[i+1] = 0; xmm6.w[i+2] = 409; xmm6.w[i+3] = 1;
|
| +; xmm5.w[i] = 298; xmm5.w[i+1] = -100; xmm5.w[i+2] = -208; xmm5.w[i+3] = 1;
|
| +; xmm4.w[i] = 298; xmm4.w[i+1] = 516; xmm4.w[i+2] = 0; xmm4.w[i+3] = 1;
|
| +; }
|
| +;
|
| +%define XMM_CONST_BIAS xmm7
|
| +%define XMM_CONST_R xmm6
|
| +%define XMM_CONST_G xmm5
|
| +%define XMM_CONST_B xmm4
|
| +
|
| +;
|
| +; READ_YUV %1 (imm8)
|
| +; Read YUV pixels and pack them. This macro stores the result pixels to xmm0 and
|
| +; xmm1 as listed below. (This macro sets xmm0.w[3], xmm0.w[7], xmm1.w[3], and
|
| +; xmm1.w[7] to 128 so we can add 128.)
|
| +; xmm0.w[0] = Y(0) - 16; xmm0.w[1] = U(0) - 128;
|
| +; xmm0.w[2] = V(0) - 128; xmm0.w[3] = 128;
|
| +; xmm0.w[4] = Y(1) - 16; xmm0.w[5] = U(0) - 128;
|
| +; xmm0.w[6] = V(0) - 128; xmm0.w[7] = 128;
|
| +; xmm1.w[0] = Y(2) - 16; xmm1.w[1] = U(1) - 128;
|
| +; xmm1.w[2] = V(1) - 128; xmm1.w[3] = 128;
|
| +; xmm1.w[4] = Y(3) - 16; xmm1.w[5] = U(1) - 128;
|
| +; xmm1.w[6] = V(1) - 128; xmm1.w[7] = 128;
|
| +;
|
| +%macro READ_YUV 1
|
| + ; Create a zero register so we can used it for unpacking pixels.
|
| + pxor xmm2, xmm2
|
| +
|
| + ; Read Y pixels.
|
| + ; xmm0.b[0] = Y(0); xmm0.b[4] = Y(1); xmm0.b[8] = Y(2); xmm0.b[12] = Y(3);
|
| +%if %1 == 1
|
| + movzx TEMPd, BYTE [Yq + WIDTHq * 2]
|
| + movd xmm0, TEMPd
|
| +%elif %1 == 2
|
| + movzx TEMPd, WORD [Yq + WIDTHq * 2]
|
| + movd xmm0, TEMPd
|
| +%elif %1 == 4
|
| + movd xmm0, DWORD [Yq + WIDTHq * 2]
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| +
|
| + ; Read U pixels.
|
| + ; xmm0.b[1] = U(0); xmm0.b[5] = U(0); xmm0.b[9] = U(1); xmm0.b[13] = U(1);
|
| +%if %1 == 1 || %1 == 2
|
| + movzx TEMPd, BYTE [Uq + WIDTHq]
|
| +%elif %1 == 4
|
| + movzx TEMPd, WORD [Uq + WIDTHq]
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| + movd xmm1, TEMPd
|
| + punpcklbw xmm1, xmm1
|
| + punpcklbw xmm0, xmm1
|
| +
|
| + ; Read V pixels.
|
| + ; xmm0.b[2] = V(0); xmm0.b[6] = V(0); xmm0.b[10] = V(1); xmm0.b[14] = V(1);
|
| +%if %1 == 1 || %1 == 2
|
| + movzx TEMPd, BYTE [Vq + WIDTHq]
|
| +%elif %1 == 4
|
| + movzx TEMPd, WORD [Vq + WIDTHq]
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| + movd xmm1, TEMPd
|
| + punpcklbw xmm1, xmm1
|
| + punpcklbw xmm1, xmm2
|
| + punpcklwd xmm0, xmm1
|
| +
|
| + ; Unpack the input 8-bit pixels to 16-bit words and remove their offsets.
|
| +%if %1 ==1 || %1 == 2
|
| + punpcklbw xmm0, xmm2
|
| +
|
| + paddsw xmm0, XMM_CONST_BIAS
|
| +%elif %1 == 4
|
| + movdqa xmm1, xmm0
|
| + punpckhbw xmm1, xmm2
|
| + punpcklbw xmm0, xmm2
|
| +
|
| + paddsw xmm0, XMM_CONST_BIAS
|
| + paddsw xmm1, XMM_CONST_BIAS
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| +%endmacro
|
| +
|
| +;
|
| +; CALC_R %1 (xmm), %2 (xmm), %3 (imm)
|
| +; Calculate four red pixels from four packed YUV pixels stored in %2.
|
| +;
|
| +%macro CALC_R 3
|
| + pmaddwd %1, XMM_CONST_R
|
| +%if %3 == 1 || %3 == 2
|
| + phaddd %1, %1
|
| +%elif %3 == 4
|
| + pmaddwd %2, XMM_CONST_R
|
| + phaddd %1, %2
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| + psrad %1, 8
|
| +
|
| + packssdw %1, %1
|
| + packuswb %1, %1
|
| +%endmacro
|
| +
|
| +;
|
| +; CALC_G %1 (xmm), %2 (xmm), %3 (imm)
|
| +; Calculate four green pixels from four packed YUV pixels stored in %2.
|
| +;
|
| +%macro CALC_G 3
|
| + pmaddwd %1, XMM_CONST_G
|
| +%if %3 == 1 || %3 == 2
|
| + phaddd %1, %1
|
| +%elif %3 == 4
|
| + pmaddwd %2, XMM_CONST_G
|
| + phaddd %1, %2
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| + psrad %1, 8
|
| +
|
| + packssdw %1, %1
|
| + packuswb %1, %1
|
| +%endmacro
|
| +
|
| +;
|
| +; CALC_B %1 (xmm), %2 (xmm), %3 (imm)
|
| +; Calculate four blue pixels from four packed YUV pixels stored in %2.
|
| +;
|
| +%macro CALC_B 3
|
| + pmaddwd %1, XMM_CONST_B
|
| +%if %3 == 1 || %3 == 2
|
| + phaddd %1, %1
|
| +%elif %3 == 4
|
| + pmaddwd %2, XMM_CONST_B
|
| + phaddd %1, %2
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| + psrad %1, 8
|
| +
|
| + packssdw %1, %1
|
| + packuswb %1, %1
|
| +%endmacro
|
| +
|
| +;
|
| +; PACK_ARGB %1 (xmm), %2 (xmm), %3 (xmm)
|
| +; Create four ARGB pixels from R pixels stored in %1, G pixels stored in %2, and
|
| +; B pixels stored in %3, respecticely. This macro assumes the input pixels are
|
| +; stored in the following format.
|
| +; %1.b[0] = B(0); %1.b[1] = B(1); %1.b[2] = B(2); %1.b[3] = B(3);
|
| +; %2.b[0] = G(0); %2.b[1] = G(1); %2.b[2] = G(2); %2.b[3] = G(3);
|
| +; %3.b[0] = R(0); %3.b[1] = R(1); %3.b[2] = R(2); %3.b[3] = R(3);
|
| +; This macro writes the output ARGB pixels in the following format:
|
| +; %1.b[0] = B(0); %1.b[1] = G(0); %1.b[2] = R(0); %1.b[3] = 0 or 255;
|
| +; %1.b[4] = B(1); %1.b[5] = G(1); %1.b[6] = R(1); %1.b[7] = 0 or 255;
|
| +; %1.b[8] = B(1); %1.b[9] = G(2); %1.b[10] = R(2); %1.b[11] = 0 or 255;
|
| +; %1.b[12] = B(1); %1.b[13] = G(3); %1.b[14] = R(3); %1.b[15] = 0 or 255;
|
| +;
|
| +%macro PACK_ARGB 3
|
| +%if ALPHA == 255
|
| + pcmpeqd xmm3, xmm3
|
| +%elif ALPHA == 0
|
| + pxor xmm3, xmm3
|
| +%else
|
| +%error unsupported ALPHA value.
|
| +%endif
|
| + punpcklbw %1, %2
|
| + punpcklbw %3, xmm3
|
| + punpcklwd %1, %3
|
| +%endmacro
|
| +
|
| +;
|
| +; PACK_RGB %1 (xmm), %2 (imm)
|
| +; Packs one ARGB pixel to an RGB pixel.
|
| +; for (int i = 0; i < %2; ++i) %1.b[i] = %1.b[i];
|
| +; for (int i = %2; i < 15; ++i) %1.b[i] = %1.b[i + 1];
|
| +;
|
| +%macro PACK_RGB 2
|
| + movdqa xmm1, %1
|
| + psrldq xmm1, %2
|
| + pslldq xmm1, %2
|
| + pxor %1, xmm1
|
| + psrldq xmm1, 1
|
| + por %1, xmm1
|
| +%endmacro
|
| +
|
| +;
|
| +; WRITE_ARGB %1 (xmm), %2 (imm)
|
| +; Write the specified number of ARGB pixels stored in the source xmm register to
|
| +; the output buffer. When the output pixel format is RGB, we convert ARGB pixels
|
| +; to RGB pixels and output them.
|
| +;
|
| +%macro WRITE_ARGB 2
|
| +
|
| +%if PIXELSIZE == 4
|
| +
|
| + ; Write ARGB pixels to the destination buffer.
|
| +%if %2 == 1
|
| + movd DWORD [ARGBq + WIDTHq * 4 * 2], %1
|
| +%elif %2 == 2
|
| + movq QWORD [ARGBq + WIDTHq * 4 * 2], %1
|
| +%elif %2 == 4
|
| + movdqu DQWORD [ARGBq + WIDTHq * 4 * 2], %1
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| +
|
| +%elif PIXELSIZE == 3
|
| +
|
| + ; Write RGB pixels to the destination buffer.
|
| +%if %2 == 1
|
| + ; Save the WIDTH register to xmm1. This macro breaks the register.
|
| + MOVq xmm1, WIDTHq
|
| +
|
| + ; Write three bytes to the destination buffer. (We do not use maskmovdqu since
|
| + ; it cause out-of-bound reads. Instead, we copy the source register to TEMPd
|
| + ; and store it.)
|
| + lea WIDTHq, [WIDTHq + WIDTHq * 2]
|
| + movd TEMPd, %1
|
| + mov WORD [ARGBq + WIDTHq * 2], TEMPw
|
| + sar TEMPw, 16
|
| + mov BYTE [ARGBq + WIDTHq * 2 + 2], TEMPb
|
| +
|
| + ; Restore the WIDTH register.
|
| + MOVq WIDTHq, xmm1
|
| +%elif %2 == 2
|
| + ; Pack two ARGB pixels to two RGB pixels.
|
| + PACK_RGB %1, 4
|
| +
|
| + ; Save the WIDTH register to xmm1. This macro breaks the register.
|
| + MOVq xmm1, WIDTHq
|
| +
|
| + ; Write six bytes to the destination buffer.
|
| + lea WIDTHq, [WIDTHq + WIDTHq * 2]
|
| + movd DWORD [ARGBq + WIDTHq * 2], %1
|
| + psrldq %1, 4
|
| + movd TEMPd, %1
|
| + mov WORD [ARGBq + WIDTHq * 2 + 4], TEMPw
|
| +
|
| + ; Restore the WIDTH register.
|
| + MOVq WIDTHq, xmm1
|
| +%elif %2 == 4
|
| + ; Pack four ARGB pixels to four RGB pixels.
|
| + PACK_RGB xmm0, 12
|
| + PACK_RGB xmm0, 8
|
| + PACK_RGB xmm0, 4
|
| +
|
| + ; Write twelve bytes to the destination buffer.
|
| + mov TEMPq, WIDTHq
|
| + lea TEMPq, [TEMPq + TEMPq * 2]
|
| + movq QWORD [ARGBq + TEMPq * 2], %1
|
| + psrldq %1, 8
|
| + movd DWORD [ARGBq + TEMPq * 2 + 8], %1
|
| +%else
|
| +%error unsupported number of pixels.
|
| +%endif
|
| +
|
| +%else
|
| +%error unsupported PIXELSIZE value.
|
| +%endif
|
| +
|
| +%endmacro
|
| +
|
| +;
|
| +; void media::simd::ConvertYUVtoARGBRow(const uint8* y,
|
| +; const uint8* u,
|
| +; const uint8* v,
|
| +; const uint8* argb,
|
| +; int width);
|
| +;
|
| +%ifdef MACHO
|
| +%define SYMBOL __ZN5media4simd19ConvertYUVtoARGBRowEPKhS2_S2_Phi
|
| +%elifdef ELF
|
| +%define SYMBOL _ZN5media4simd19ConvertYUVtoARGBRowEPKhS2_S2_Phi
|
| +%elifdef MSVC
|
| +%define SYMBOL ?ConvertYUVtoARGBRow@simd@media@@YAXPBE00PAEH@Z
|
| +%endif
|
| +%define PIXELSIZE 4
|
| +%define ALPHA 255
|
| +
|
| +%include "convert_yuv_to_rgb_ssse3.inc"
|
| +
|
| +;
|
| +; void media::simd::ConvertYUVtoRGBRow(const uint8* y,
|
| +; const uint8* u,
|
| +; const uint8* v,
|
| +; const uint8* rgb,
|
| +; int width);
|
| +;
|
| +%ifdef MACHO
|
| +%define SYMBOL __ZN5media4simd18ConvertYUVtoRGBRowEPKhS2_S2_Phi
|
| +%elifdef ELF
|
| +%define SYMBOL _ZN5media4simd18ConvertYUVtoRGBRowEPKhS2_S2_Phi
|
| +%elifdef MSVC
|
| +%define SYMBOL ?ConvertYUVtoRGBRow@simd@media@@YAXPBE00PAEH@Z
|
| +%endif
|
| +%define PIXELSIZE 3
|
| +%define ALPHA 0
|
| +%include "convert_yuv_to_rgb_ssse3.inc"
|
|
|