Chromium Code Reviews| Index: media/base/simd/yuv_row_rgb.inc |
| =================================================================== |
| --- media/base/simd/yuv_row_rgb.inc (revision 0) |
| +++ media/base/simd/yuv_row_rgb.inc (revision 0) |
| @@ -0,0 +1,520 @@ |
| +; Copyright (c) 2011 The Chromium Authors. All rights reserved. |
|
Alpha Left Google
2011/08/22 14:16:59
Rename this to media/base/yuv_row_rgb2yuv_sse2.inc
|
| +; Use of this source code is governed by a BSD-style license that can be |
| +; found in the LICENSE file. |
| + |
| +; |
| +; void media::simd::ConvertARGBtoYUVRow(const uint8* argb, |
| +; uint8* y, |
| +; uint8* u, |
| +; uint8* v, |
| +; int width); |
| +; void media::simd::ConvertRGBtoYUVRow(const uint8* rgb, |
| +; uint8* y, |
| +; uint8* u, |
| +; uint8* v, |
| +; int width); |
| +; |
| +; Converts a row of ARGB (RGB) pixels to the YUV (4:1:1) colorspace. This |
| +; function reads ARGB (RGB) pixels from right to left, convert their colorspace |
| +; to YUV, and write the converted pixels to the output buffers. The following |
| +; code snippetre presents the rough structure of this fucntion. |
| +; |
| +; if (width & 1) { |
| +; --width; |
| +; convert_one_pixel(argb, y, u, v, width); |
| +; } |
| +; if (width & 2) { |
| +; width -= 2; |
| +; convert_two_pixels(argb, y, u, v, width); |
| +; } |
| +; while (width) { |
| +; width -= 4; |
| +; convert_four_pixels(argb, y, u, v, width); |
| +; } |
| +; |
| +; This function has pseudo-code snippets to describe its behaviors. For |
| +; simplicity, they use the following notations. |
| +; |
| +; #define B(n) argb[n * PIXELSIZE + 0]; |
| +; #define G(n) argb[n * PIXELSIZE + 1]; |
| +; #define R(n) argb[n * PIXELSIZE + 2]; |
| +; #define A(n) PIXELSIZE == 4 ? ARGB[n * PIXELSIZE + 3] : 0; |
| +; #define FIX(n) (n * (1 << SHIFT_BITS) + 0.5) |
| +; #define ToByte(n) ((n < 0) ? 0 : (n > 255 ? 255 : n)) |
| +; |
| +; union { |
| +; int32 d[4]; |
| +; int16 w[8]; |
| +; int8 b[16]; |
| +; } xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 |
| +; |
| + |
| +; Input Parameters |
| +%ifdef __x86_64__ |
| +%ifdef WIN64 |
| +%define PARAM_ARGB(r) rcx |
| +%define PARAM_Y(r) rdx |
| +%define PARAM_U(r) r8 |
| +%define PARAM_V(r) r9 |
| +%define PARAM_WIDTH(r) INT [(r) + SIZEOF_POINTER * 2] |
| +%else |
| +%define PARAM_ARGB(r) rdi |
| +%define PARAM_Y(r) rsi |
| +%define PARAM_U(r) rdx |
| +%define PARAM_V(r) rcx |
| +%define PARAM_WIDTH(r) r8 |
| +%endif |
| +%else |
| +%define PARAM_ARGB(r) POINTER [(r) + SIZEOF_POINTER * 2] |
| +%define PARAM_Y(r) POINTER [(r) + SIZEOF_POINTER * 2 + SIZEOF_POINTER * 1] |
| +%define PARAM_U(r) POINTER [(r) + SIZEOF_POINTER * 2 + SIZEOF_POINTER * 2] |
| +%define PARAM_V(r) POINTER [(r) + SIZEOF_POINTER * 2 + SIZEOF_POINTER * 3] |
| +%define PARAM_WIDTH(r) INT [(r) + SIZEOF_POINTER * 2 + SIZEOF_POINTER * 4] |
| +%endif ; __x86_64__ |
| + |
| +; Local variables used in this function. |
| +%define INT_WIDTH32 eax |
| +%define INT_WIDTH8 al |
| + |
| +%define INT_PIXEL32 ebx |
| +%define INT_PIXEL16 bx |
| +%define INT_PIXEL8 bl |
| + |
| +%ifdef __x86_64__ |
| +%define INT_WIDTH rax |
| +%define INT_PIXEL rbx |
| +%define PTR_ARGB PARAM_ARGB(_EBP_) |
| +%define PTR_Y PARAM_Y(_EBP_) |
| +%define PTR_U PARAM_U(_EBP_) |
| +%define PTR_V PARAM_V(_EBP_) |
| +%else |
| +%define INT_WIDTH eax |
| +%define INT_PIXEL ebx |
| +%define PTR_ARGB ecx |
| +%define PTR_Y edx |
| +%define PTR_U esi |
| +%define PTR_V edi |
| +%endif |
| + |
| +%define XMM_TABLE_Y xmm7 |
| +%define XMM_TABLE_0_5 xmm6 |
| +%define XMM_TABLE_UV xmm5 |
| +%define XMM_ZERO xmm4 |
| + |
| +; SECTION SEG_TEXT |
| +; CPU PENTIUM4 |
| + |
| + align 16 |
| + global EXTN(SYMBOL_NAME) PRIVATE |
| + |
| +EXTN(SYMBOL_NAME): |
| + push _EBP_ |
| + mov _EBP_, _ESP_ |
| + |
| + ; Save the resisters used in this function. We do not need to save eax, ecx, |
| + ; or edx even though this function uses them. (Callers save them.) |
| + push _EBX_ |
| + push _ESI_ |
| + push _EDI_ |
| + |
| + ; Copy the tables used in this function to xmm5, xmm6, and xmm7. |
| + LOADSYM _EAX_, SIMD_ConvertARGBToYUVRow_kTable |
| + movdqa XMM_TABLE_Y, XMMWORD [_EAX_ + 16 * 0] |
| + movdqa XMM_TABLE_0_5, XMMWORD [_EAX_ + 16 * 1] |
| + movdqa XMM_TABLE_UV, XMMWORD [_EAX_ + 16 * 2] |
| + |
| + ; Copy the input parameters to registers. (We can use the input pointers on |
| + ; x86-64 since we do not change them.) |
| + mov INT_WIDTH, PARAM_WIDTH(_EBP_) |
| +%ifndef __x86_64__ |
| + mov PTR_ARGB, PARAM_ARGB(_EBP_) |
| + mov PTR_Y, PARAM_Y(_EBP_) |
| + mov PTR_U, PARAM_U(_EBP_) |
| + mov PTR_V, PARAM_V(_EBP_) |
| +%endif |
| + |
| +.convert_one_pixel: |
| + ; Divide the input width by two so it represents the offsets for u[] and v[]. |
| + ; When the width is odd. Wee read the rightmost ARGB pixel and convert its |
| + ; colorspace to YUV. This code stores one Y pixel, one U pixel, and one V |
| + ; pixel. |
| + sar INT_WIDTH, 1 |
| + jnc .convert_two_pixels |
| + |
| + ; xmm0.w[0] = B(0); xmm0.w[1] = G(0); xmm0.w[2] = R(0); xmm0.w[3] = A(0); |
| +%if PIXELSIZE == 4 |
| + movd xmm0, DWORD [PTR_ARGB + INT_WIDTH * 4 * 2] |
| +%elif PIXELSIZE == 3 |
| + movd xmm1, INT_WIDTH |
| + lea INT_WIDTH, [INT_WIDTH + INT_WIDTH * 2] |
| + movzx INT_PIXEL32, BYTE [PTR_ARGB + INT_WIDTH * 2 + 2] |
| + shl INT_PIXEL32, 16 |
| + mov INT_PIXEL16, WORD [PTR_ARGB + INT_WIDTH * 2] |
| + movd xmm0, INT_PIXEL32 |
| + movd INT_WIDTH, xmm1 |
| +%else |
| +%error unsupported pixel size. |
| +%endif |
| + pxor XMM_ZERO, XMM_ZERO |
| + punpcklbw xmm0, XMM_ZERO |
| + |
| + ; xmm2.d[0] = FIX(0.098) * B(0) + FIX(0.504) * G(0); |
| + ; xmm2.d[1] = FIX(0.257) * R(0) + FIX(0.000) * A(0); |
| + movdqa xmm2, xmm0 |
| + pmaddwd xmm2, XMM_TABLE_Y |
| + |
| + ; xmm2.d[0] = (xmm2.d[0] + xmm2.d[1] + FIX(0.5)) / FIX(1) + 16; |
| + pshufd xmm4, xmm2, 10001000B |
| + pshufd xmm2, xmm2, 11011101B |
| + paddd xmm2, xmm4 |
| + |
| + paddd xmm2, XMM_TABLE_0_5 |
| + psrad xmm2, SHIFT_BITS |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 5 |
| + paddd xmm2, xmm3 |
| + |
| + ; y[0] = ToByte(xmm2.d[0]); |
| + packssdw xmm2, xmm2 |
| + packuswb xmm2, xmm2 |
| + movd INT_PIXEL32, xmm2 |
| + mov BYTE [PTR_Y + INT_WIDTH * 2], INT_PIXEL8 |
| + |
| + ; Calculate u[0] from xmm0. |
| + test PTR_U, PTR_U |
| + jz .convert_two_pixels |
| + |
| + ; xmm1.d[0] = FIX(0.439) * B(0) + -FIX(0.291) * G(0); |
| + ; xmm1.d[1] = -FIX(0.148) * R(0) + FIX(0.000) * A(0); |
| + movdqa xmm1, xmm0 |
| + pshufd xmm2, XMM_TABLE_UV, 01000100B |
| + pmaddwd xmm1, xmm2 |
| + |
| + ; xmm1.d[0] = (xmm1.d[0] + xmm1.d[1] + FIX(0.5)) / FIX(1) + 128; |
| + pshufd xmm2, xmm1, 11011101B |
| + pshufd xmm1, xmm1, 10001000B |
| + paddd xmm1, xmm2 |
| + paddd xmm1, XMM_TABLE_0_5 |
| + psrad xmm1, SHIFT_BITS |
| +%if SHIFT_BITS == 8 |
| + paddd xmm1, XMM_TABLE_0_5 |
| +%else |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 8 |
| + paddd xmm1, xmm3 |
| +%endif |
| + |
| + ; u[0] = ToByte(xmm1.d[0]); |
| + packssdw xmm1, xmm1 |
| + packuswb xmm1, xmm1 |
| + movd INT_PIXEL32, xmm1 |
| + mov BYTE [PTR_U + INT_WIDTH], INT_PIXEL8 |
| + |
| + ; Calculate v[0] from xmm0. |
| + ; xmm0.d[0] = -FIX(0.071) * B(0) + -FIX(0.368) * G(0); |
| + ; xmm0.d[1] = FIX(0.439) * R(0) + FIX(0.000) * A(0); |
| + pshufd xmm2, XMM_TABLE_UV, 11101110B |
| + pmaddwd xmm0, xmm2 |
| + |
| + ; xmm0.d[0] = (xmm0.d[0] + xmm0.d[1] + FIX(0.5)) / FIX(1) + 128; |
| + pshufd xmm2, xmm0, 11011101B |
| + pshufd xmm1, xmm0, 10001000B |
| + paddd xmm0, xmm2 |
| + paddd xmm0, XMM_TABLE_0_5 |
| + psrad xmm0, SHIFT_BITS |
| +%if SHIFT_BITS == 8 |
| + paddd xmm0, XMM_TABLE_0_5 |
| +%else |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 8 |
| + paddd xmm0, xmm3 |
| +%endif |
| + |
| + ; v[0] = ToByte(xmm0.d[0]); |
| + packssdw xmm0, xmm0 |
| + packuswb xmm0, xmm0 |
| + movd INT_PIXEL32, xmm0 |
| + mov BYTE [PTR_V + INT_WIDTH], INT_PIXEL8 |
| + |
| +.convert_two_pixels: |
| + ; If the input width is not a multiple of four, read the rightmost two ARGB |
| + ; pixels and convert their colorspace to YUV. This code stores two Y pixels, |
| + ; one U pixel, and one V pixel. |
| + test INT_WIDTH8, 2 / 2 |
| + jz .convert_four_pixels |
| + sub INT_WIDTH8, 2 / 2 |
| + |
| + ; xmm0.w[0] = B(0); xmm0.w[1] = G(0); xmm0.w[2] = R(0); xmm0.w[3] = A(0); |
| + ; xmm0.w[4] = B(1); xmm0.w[5] = G(1); xmm0.w[6] = R(1); xmm0.w[7] = A(1); |
| +%if PIXELSIZE == 4 |
| + movq xmm0, MMWORD [PTR_ARGB + INT_WIDTH * 4 * 2] |
| +%elif PIXELSIZE == 3 |
| + mov _EBX_, INT_WIDTH |
| + lea _EBX_, [_EBX_ + _EBX_ * 2] |
| + movd xmm0, DWORD [PTR_ARGB + _EBX_ * 2] |
| + pinsrw xmm0, WORD [PTR_ARGB + _EBX_ * 2 + 4], 3 |
| + movdqa xmm1, xmm0 |
| + psrldq xmm1, 3 |
| + pslldq xmm1, 3 |
| + pxor xmm0, xmm1 |
| + pslldq xmm1, 1 |
| + por xmm0, xmm1 |
| +%else |
| +%error unsupported pixel size. |
| +%endif |
| + pxor XMM_ZERO, XMM_ZERO |
| + punpcklbw xmm0, XMM_ZERO |
| + |
| + ; xmm2.d[0] = FIX(0.098) * B(0) + FIX(0.504) * G(0); |
| + ; xmm2.d[1] = FIX(0.257) * R(0) + FIX(0.000) * A(0) ; |
| + ; xmm2.d[2] = FIX(0.098) * B(1) + FIX(0.504) * G(1); |
| + ; xmm2.d[3] = FIX(0.257) * R(1) + FIX(0.000) * A(1); |
| + movdqa xmm2, xmm0 |
| + pmaddwd xmm2, XMM_TABLE_Y |
| + |
| + ; xmm2.d[0] = (xmm2.d[0] + xmm2.d[1] + FIX(0.5)) / FIX(1) + 16; |
| + ; xmm2.d[1] = (xmm2.d[2] + xmm2.d[3] + FIX(0.5)) / FIX(1) + 16; |
| + pshufd xmm4, xmm2, 10001000B |
| + pshufd xmm2, xmm2, 11011101B |
| + paddd xmm2, xmm4 |
| + |
| + paddd xmm2, XMM_TABLE_0_5 |
| + psrld xmm2, SHIFT_BITS |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrld xmm3, SHIFT_BITS - 5 |
| + paddd xmm2, xmm3 |
| + |
| + ; y[0] = ToByte(xmm2.d[0]); y[1] = ToByte(xmm2.d[1]); |
| + packssdw xmm2, xmm2 |
| + packuswb xmm2, xmm2 |
| + movd INT_PIXEL32, xmm2 |
| + mov WORD [PTR_Y + INT_WIDTH * 2], INT_PIXEL16 |
| + |
| + ; Calculate u[0] from xmm0. |
| + test PTR_U, PTR_U |
| + jz .convert_four_pixels |
| + |
| + ; xmm1.d[0] = FIX(0.439) * B(0) + -FIX(0.291) * G(0); |
| + ; xmm1.d[1] = -FIX(0.148) * R(0) + FIX(0.000) * A(0); |
| + movdqa xmm1, xmm0 |
| + pshufd xmm2, XMM_TABLE_UV, 01000100B |
| + pmaddwd xmm1, xmm2 |
| + |
| + ; xmm1.d[0] = (xmm1.d[0] + xmm1.d[1] + FIX(0.5)) / FIX(1) + 128; |
| + pshufd xmm2, xmm1, 11011101B |
| + pshufd xmm1, xmm1, 10001000B |
| + paddd xmm1, xmm2 |
| + paddd xmm1, XMM_TABLE_0_5 |
| + psrad xmm1, SHIFT_BITS |
| +%if SHIFT_BITS == 8 |
| + paddd xmm1, XMM_TABLE_0_5 |
| +%else |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 8 |
| + paddd xmm1, xmm3 |
| +%endif |
| + |
| + ; u[0] = ToByte(xmm1.d[0]); |
| + packssdw xmm1, xmm1 |
| + packuswb xmm1, xmm1 |
| + movd INT_PIXEL32, xmm1 |
| + mov BYTE [PTR_U + INT_WIDTH], INT_PIXEL8 |
| + |
| + ; Calculate v[0] from xmm0. |
| + ; xmm0.d[0] = -FIX(0.071) * B(0) + -FIX(0.368) * G(0); |
| + ; xmm0.d[1] = FIX(0.439) * R(0) + FIX(0.000) * A(0); |
| + pshufd xmm2, XMM_TABLE_UV, 11101110B |
| + pmaddwd xmm0, xmm2 |
| + |
| + ; xmm0.d[0] = (xmm0.d[0] + xmm0.d[1] + FIX(0.5)) / FIX(1) + 128; |
| + pshufd xmm2, xmm0, 11011101B |
| + pshufd xmm0, xmm0, 10001000B |
| + paddd xmm0, xmm2 |
| + paddd xmm0, XMM_TABLE_0_5 |
| + psrad xmm0, SHIFT_BITS |
| +%if SHIFT_BITS == 8 |
| + paddd xmm0, XMM_TABLE_0_5 |
| +%else |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 8 |
| + paddd xmm0, xmm3 |
| +%endif |
| + |
| + ; v[0] = ToByte(xmm0.d[0]); |
| + packssdw xmm0, xmm0 |
| + packuswb xmm0, xmm0 |
| + movd INT_PIXEL32, xmm0 |
| + mov BYTE [PTR_V + INT_WIDTH], INT_PIXEL8 |
| + |
| +.convert_four_pixels: |
| + ; Read four ARGB pixels and convert their colorspace to YUV. This code stores |
| + ; four Y pixels, two U pixels, and two V pixels. |
| + test INT_WIDTH32, INT_WIDTH32 |
| + jz .convert_finish |
| + |
| +.convert_four_pixels_main: |
| + sub INT_WIDTH32, 4 / 2 |
| + |
| + ; xmm0.w[0] = B(0); xmm0.w[1] = G(0); xmm0.w[2] = R(0); xmm0.w[3] = A(0); |
| + ; xmm0.w[4] = B(1); xmm0.w[5] = G(1); xmm0.w[6] = R(1); xmm0.w[7] = A(1); |
| + ; xmm1.w[0] = B(2); xmm1.w[1] = G(2); xmm1.w[2] = R(2); xmm1.w[3] = A(2); |
| + ; xmm1.w[4] = B(3); xmm1.w[5] = G(3); xmm1.w[6] = R(3); xmm1.w[7] = A(3); |
| +%if PIXELSIZE == 4 |
| + movdqa xmm0, XMMWORD [PTR_ARGB + INT_WIDTH * 4 * 2] |
| +%elif PIXELSIZE == 3 |
| + mov _EBX_, INT_WIDTH |
| + lea _EBX_, [_EBX_ + _EBX_ * 2] |
| + movq xmm0, MMWORD [PTR_ARGB + _EBX_ * 2] |
| + movd xmm1, DWORD [PTR_ARGB + _EBX_ * 2 + 8] |
| + shufps xmm0, xmm1, 01000100B |
| + movdqa xmm1, xmm0 |
| + psrldq xmm1, 6 |
| + pslldq xmm1, 6 |
| + pxor xmm0, xmm1 |
| + |
| + movdqa xmm2, xmm0 |
| + psrldq xmm2, 3 |
| + pslldq xmm2, 3 |
| + pxor xmm0, xmm2 |
| + pslldq xmm2, 1 |
| + por xmm0, xmm2 |
| + |
| + movdqa xmm3, xmm1 |
| + psrldq xmm3, 6 + 3 |
| + pslldq xmm3, 6 + 3 |
| + pxor xmm1, xmm3 |
| + pslldq xmm3, 1 |
| + por xmm1, xmm3 |
| + |
| + pslldq xmm1, 2 |
| + por xmm0, xmm1 |
| +%else |
| +%error unsupported pixel size. |
| +%endif |
| + movdqa xmm1, xmm0 |
| + pxor XMM_ZERO, XMM_ZERO |
| + punpckhbw xmm1, XMM_ZERO |
| + punpcklbw xmm0, XMM_ZERO |
| + |
| + ; xmm2.d[0] = FIX(0.098) * B(0) + FIX(0.504) * G(0); |
| + ; xmm2.d[1] = FIX(0.257) * R(0) + FIX(0.000) * A(0); |
| + ; xmm2.d[2] = FIX(0.098) * B(1) + FIX(0.504) * G(1); |
| + ; xmm2.d[3] = FIX(0.257) * R(1) + FIX(0.000) * A(1); |
| + ; xmm3.d[0] = FIX(0.098) * B(2) + FIX(0.504) * G(2); |
| + ; xmm3.d[1] = FIX(0.257) * R(2) + FIX(0.000) * A(2); |
| + ; xmm3.d[2] = FIX(0.098) * B(3) + FIX(0.504) * G(3); |
| + ; xmm3.d[3] = FIX(0.257) * R(3) + FIX(0.000) * A(3); |
| + movdqa xmm2, xmm0 |
| + movdqa xmm3, xmm1 |
| + pmaddwd xmm2, XMM_TABLE_Y |
| + pmaddwd xmm3, XMM_TABLE_Y |
| + |
| + ; xmm2.d[0] = (xmm2.d[0] + xmm2.d[1] + FIX(0.5)) / FIX(1) + 16; |
| + ; xmm2.d[1] = (xmm2.d[2] + xmm2.d[3] + FIX(0.5)) / FIX(1) + 16; |
| + ; xmm2.d[2] = (xmm3.d[0] + xmm3.d[1] + FIX(0.5)) / FIX(1) + 16; |
| + ; xmm2.d[3] = (xmm3.d[2] + xmm3.d[3] + FIX(0.5)) / FIX(1) + 16; |
| + movdqa xmm4, xmm2 |
| + shufps xmm4, xmm3, 10001000B |
| + shufps xmm2, xmm3, 11011101B |
| + paddd xmm2, xmm4 |
| + |
| + paddd xmm2, XMM_TABLE_0_5 |
| + psrad xmm2, SHIFT_BITS |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 5 |
| + paddd xmm2, xmm3 |
| + |
| + ; y[0] = ToByte(xmm2.d[0]); y[1] = ToByte(xmm2.d[1]); |
| + ; y[2] = ToByte(xmm2.d[2]); y[3] = ToByte(xmm2.d[3]); |
| + packssdw xmm2, xmm2 |
| + packuswb xmm2, xmm2 |
| + movd DWORD [PTR_Y + INT_WIDTH * 2], xmm2 |
| + |
| + ; Retrieve (R(0), G(0), B(0), A(0)) and (R(2), G(2), B(2), A(2)) from xmm1 |
| + ; and xmm1. |
| + ; xmm0.w[0] = B(0); xmm0.w[1] = G(0); xmm0.w[2] = R(0); xmm0.w[3] = A(0); |
| + ; xmm0.w[4] = B(2); xmm0.w[5] = G(2); xmm0.w[6] = R(2); xmm0.w[7] = A(2); |
| + shufps xmm0, xmm1, 01000100B |
| + |
| + ; Calculate u[0] and u[2] from xmm0. |
| + test PTR_U, PTR_U |
| + jz .convert_four_pixels_next |
| + |
| + ; xmm1.d[0] = FIX(0.439) * B(0) + -FIX(0.291) * G(0); |
| + ; xmm1.d[1] = -FIX(0.148) * R(0) + FIX(0.000) * A(0); |
| + ; xmm1.d[2] = FIX(0.439) * B(2) + -FIX(0.291) * G(2); |
| + ; xmm1.d[3] = -FIX(0.148) * R(2) + FIX(0.000) * A(2); |
| + movdqa xmm1, xmm0 |
| + pshufd xmm2, XMM_TABLE_UV, 01000100B |
| + pmaddwd xmm1, xmm2 |
| + |
| + ; xmm1.d[0] = (xmm1.d[0] + xmm1.d[1] + FIX(0.5)) / FIX(1) + 128; |
| + ; xmm1.d[1] = (xmm1.d[2] + xmm1.d[3] + FIX(0.5)) / FIX(1) + 128; |
| + pshufd xmm2, xmm1, 11011101B |
| + pshufd xmm1, xmm1, 10001000B |
| + paddd xmm1, xmm2 |
| + paddd xmm1, XMM_TABLE_0_5 |
| + psrad xmm1, SHIFT_BITS |
| +%if SHIFT_BITS == 8 |
| + paddd xmm1, XMM_TABLE_0_5 |
| +%else |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 8 |
| + paddd xmm1, xmm3 |
| +%endif |
| + |
| + ; u[0] = ToByte(xmm1.d[0]); u[1] = ToByte(xmm1.d[1]); |
| + packssdw xmm1, xmm1 |
| + packuswb xmm1, xmm1 |
| + movd INT_PIXEL32, xmm1 |
| + mov WORD [PTR_U + INT_WIDTH], INT_PIXEL16 |
| + |
| + ; Calculate v[0] and v[2] from xmm0. |
| + ; xmm1.d[0] = -FIX(0.071) * B(0) + -FIX(0.368) * G(0); |
| + ; xmm1.d[1] = FIX(0.439) * R(0) + FIX(0.000) * A(0); |
| + ; xmm1.d[2] = -FIX(0.071) * B(2) + -FIX(0.368) * G(2); |
| + ; xmm1.d[3] = FIX(0.439) * R(2) + FIX(0.000) * A(2); |
| + movdqa xmm1, xmm0 |
| + pshufd xmm2, XMM_TABLE_UV, 11101110B |
| + pmaddwd xmm1, xmm2 |
| + |
| + ; xmm1.d[0] = (xmm1.d[0] + xmm1.d[1] + FIX(0.5)) / FIX(1) + 128; |
| + ; xmm1.d[1] = (xmm1.d[2] + xmm1.d[3] + FIX(0.5)) / FIX(1) + 128; |
| + pshufd xmm2, xmm1, 11011101B |
| + pshufd xmm1, xmm1, 10001000B |
| + paddd xmm1, xmm2 |
| + paddd xmm1, XMM_TABLE_0_5 |
| + psrad xmm1, SHIFT_BITS |
| +%if SHIFT_BITS == 8 |
| + paddd xmm1, XMM_TABLE_0_5 |
| +%else |
| + movdqa xmm3, XMM_TABLE_0_5 |
| + psrad xmm3, SHIFT_BITS - 8 |
| + paddd xmm1, xmm3 |
| +%endif |
| + |
| + ; v[0] = ToByte(xmm1.d[0]); v[1] = ToByte(xmm1.d[1]); |
| + packssdw xmm1, xmm1 |
| + packuswb xmm1, xmm1 |
| + movd INT_PIXEL32, xmm1 |
| + mov WORD [PTR_V + INT_WIDTH], INT_PIXEL16 |
| + |
| +.convert_four_pixels_next: |
| + test INT_WIDTH32, INT_WIDTH32 |
| + jnz .convert_four_pixels_main |
| + |
| +.convert_finish: |
| + ; Restore the registers used in this function, the stack frame, and the stack |
| + ; pointer. |
| + pop _EDI_ |
| + pop _ESI_ |
| + pop _EBX_ |
| + |
| + mov _ESP_, _EBP_ |
| + pop _EBP_ |
| + |
| + ret |
| + |
| + ; For some reason, the OS X linker does not honor the request to align the |
| + ; segment unless we do this. |
| + align 16 |