Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(950)

Unified Diff: media/base/simd/convert_yuv_to_rgb_ssse3.asm

Issue 7003082: Implements RGB to YV12 conversion in YASM. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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"

Powered by Google App Engine
This is Rietveld 408576698