| Index: media/base/simd/convert_yuv_to_rgb_ssse3.inc
|
| ===================================================================
|
| --- media/base/simd/convert_yuv_to_rgb_ssse3.inc (revision 0)
|
| +++ media/base/simd/convert_yuv_to_rgb_ssse3.inc (revision 0)
|
| @@ -0,0 +1,239 @@
|
| +; 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.
|
| +
|
| +;
|
| +; void SYMBOL(const uint8* y,
|
| +; const uint8* u,
|
| +; const uint8* v,
|
| +; uint8* argb,
|
| +; int width);
|
| +;
|
| +; Converts a row of YUV (4:1:1) pixels to the ARGB (RGB) colorspace. This
|
| +; function reads YUV pixels from right to left, convert their colorspace to ARGB
|
| +; (RGB), and write the converted pixels to the output buffers. The following
|
| +; code snippet represents the rough structure of this fucntion.
|
| +;
|
| +; if (width & 1) {
|
| +; --width;
|
| +; convert_one_pixel(y, u, v, argb, width);
|
| +; }
|
| +; if (width & 2) {
|
| +; width -= 2;
|
| +; convert_two_pixels(y, u, v, argb, width);
|
| +; }
|
| +; while (width) {
|
| +; width -= 4;
|
| +; convert_four_pixels(y, u, v, argb, width);
|
| +; }
|
| +;
|
| +; This function has pseudo-code snippets to describe its behaviors. For
|
| +; simplicity, they use the following notations.
|
| +;
|
| +; #define Y(n) y[n] - 16
|
| +; #define U(n) u[n] - 128
|
| +; #define V(n) v[n] - 128
|
| +; #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
|
| +;
|
| +;
|
| + global SYMBOL PRIVATE
|
| + align function_align
|
| +
|
| +SYMBOL:
|
| + %assign stack_offset 0
|
| + PROLOGUE 5, 6, 8, Y, U, V, ARGB, WIDTH, TEMP
|
| +
|
| + ; Initialize constants used in this function.
|
| + LOAD_SYM TEMPq, SIMD_ConvertYUVtoARGB_kTable
|
| + movdqa xmm0, DQWORD [TEMPq + 0]
|
| + movdqa xmm1, DQWORD [TEMPq + 16]
|
| + pshufd XMM_CONST_BIAS, xmm0, 01000100B
|
| + pshufd XMM_CONST_R, xmm0, 11101110B
|
| + pshufd XMM_CONST_G, xmm1, 01000100B
|
| + pshufd XMM_CONST_B, xmm1, 11101110B
|
| +
|
| +.convert_one_pixel:
|
| + ; Divide the input width by two so it represents the offsets for u[] and v[].
|
| + ; When the width is odd, We 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 WIDTHq, 1
|
| + jnc .convert_two_pixels
|
| +
|
| + ; Read one Y pixel, one U pixel, and one V pixel. It packs the pixels into
|
| + ; xmm0.
|
| + READ_YUV 1
|
| +
|
| + ; Calculate r[0].
|
| + movdqa xmm2, xmm0
|
| + CALC_R xmm2, xmm3, 1
|
| + movd TEMPd, xmm2
|
| +
|
| + ; Calculate g[0].
|
| + movdqa xmm2, xmm0
|
| + CALC_G xmm2, xmm3, 1
|
| +
|
| + ; Calculate b[0].
|
| + CALC_B xmm0, xmm1, 1
|
| +
|
| + ; Interleave r[0], g[0], and b[0] to create one ARGB pixel.
|
| + movd xmm1, TEMPd
|
| + PACK_ARGB xmm0, xmm2, xmm1
|
| +
|
| +%if PIXELSIZE == 4
|
| + movd DWORD [ARGBq + WIDTHq * 4 * 2], xmm0
|
| +%else
|
| + MOVq xmm1, WIDTHq
|
| + lea WIDTHq, [WIDTHq + WIDTHq * 2]
|
| + movd TEMPd, xmm0
|
| + mov WORD [ARGBq + WIDTHq * 2], TEMPw
|
| + sar TEMPw, 16
|
| + mov BYTE [ARGBq + WIDTHq * 2 + 2], TEMPb
|
| + MOVq WIDTHq, xmm1
|
| +%endif
|
| +
|
| +.convert_two_pixels:
|
| + ; When the input width is not a multiple of four, we read the rightmost two Y
|
| + ; pixels, one U pixel, and one V pixel to convert their colorspace to RGB.
|
| + ; This code stores two RGBA pixels.
|
| + test WIDTHb, 1
|
| + jz .convert_four_pixels
|
| + sub WIDTHq, 2 / 2
|
| +
|
| + ; Read two Y pixels, one U pixels, and one V pixels to xmm0.
|
| + READ_YUV 2
|
| +
|
| + ; Calculate r[0] and r[0].
|
| + movdqa xmm2, xmm0
|
| + CALC_R xmm2, xmm3, 1
|
| + movd TEMPd, xmm2
|
| +
|
| + ; Calculate g[0].
|
| + movdqa xmm2, xmm0
|
| + CALC_G xmm2, xmm3, 1
|
| +
|
| + ; Calculate b[0].
|
| + CALC_B xmm0, xmm1, 1
|
| +
|
| + ; Interleave r[0], g[0], and b[0] to create one ARGB pixel.
|
| + movd xmm1, TEMPd
|
| + PACK_ARGB xmm0, xmm2, xmm1
|
| +
|
| +%if PIXELSIZE == 4
|
| + movq QWORD [ARGBq + WIDTHq * 4 * 2], xmm0
|
| +%else
|
| + MOVq xmm1, WIDTHq
|
| + lea WIDTHq, [WIDTHq + WIDTHq * 2]
|
| + movd DWORD [ARGBq + WIDTHq * 2], xmm0
|
| + psrldq xmm0, 4
|
| + movd TEMPd, xmm0
|
| + mov WORD [ARGBq + WIDTHq * 2 + 4], TEMPw
|
| + MOVq WIDTHq, xmm1
|
| +%endif
|
| +
|
| +.convert_four_pixels:
|
| + ; Read four Y pixels, two U pixels, and two V pixels to convert their
|
| + ; colorspace to RGB. This code stores four RGBA (or RGB) pixels.
|
| + test WIDTHq, WIDTHq
|
| + jz .convert_finish
|
| +
|
| +%if PIXELSIZE == 4
|
| + ; Check if the input buffer is aligned to a 16-byte boundary so we can use
|
| + ; movdqa for writing the ARGB pixels if possible.
|
| + test ARGBw, 15
|
| + jnz .convert_four_pixels_unaligned
|
| +
|
| +.convert_four_pixels_aligned:
|
| + sub WIDTHq, 4 / 2
|
| +
|
| + ; Read four Y pixels, two U pixels, and two V pixels to xmm0 and xmm1.
|
| + READ_YUV 4
|
| +
|
| + ; Calculate r[0],...,r[3]. It saves the results to TEMP.b[0],...,TEMP.b[3],
|
| + ; respecitively.
|
| + movdqa xmm2, xmm0
|
| + movdqa xmm3, xmm1
|
| + CALC_R xmm2, xmm3, 4
|
| + movd TEMPd, xmm2
|
| +
|
| + ; Calculate g[0],...,g[3]. It saves the results to xmm2.b[0],...,xmm2.b[3],
|
| + ; respectively.
|
| + movdqa xmm2, xmm0
|
| + movdqa xmm3, xmm1
|
| + CALC_G xmm2, xmm3, 4
|
| +
|
| + ; Calculate b[0],...,b[3]. It saves the results to xmm0.b[0],...,xmm0.b[3],
|
| + ; respectively.
|
| + CALC_B xmm0, xmm1, 4
|
| +
|
| + ; Interleave r[0],...,r[3], g[0],...,g[3], and b[0],...,b[3] to create four
|
| + ; ARGB pixels
|
| + movd xmm1, TEMPd
|
| + PACK_ARGB xmm0, xmm2, xmm1
|
| +
|
| + ; Write four ARGB pixels. (We can use movdqa here since we have checked if the
|
| + ; destination address is aligned.)
|
| + movdqa DQWORD [ARGBq + WIDTHq * 4 * 2], xmm0
|
| +
|
| + test WIDTHq, WIDTHq
|
| + jnz .convert_four_pixels_aligned
|
| +
|
| + jmp .convert_finish
|
| +%endif ; PIXELSIZE == 4
|
| +
|
| +.convert_four_pixels_unaligned:
|
| + sub WIDTHq, 4 / 2
|
| +
|
| + ; Read four Y pixels, two U pixels, and two V pixels to xmm0 and xmm1.
|
| + READ_YUV 4
|
| +
|
| + ; Calculate r[0],...,r[3]. It saves the results to TEMP.b[0],...,TEMP.b[3],
|
| + ; respecitively.
|
| + movdqa xmm2, xmm0
|
| + movdqa xmm3, xmm1
|
| + CALC_R xmm2, xmm3, 4
|
| + movd TEMPd, xmm2
|
| +
|
| + ; Calculate g[0],...,g[3]. It saves the results to xmm2.b[0],...,xmm2.b[3],
|
| + ; respectively.
|
| + movdqa xmm2, xmm0
|
| + movdqa xmm3, xmm1
|
| + CALC_G xmm2, xmm3, 4
|
| +
|
| + ; Calculate b[0],...,b[3]. It saves the results to xmm0.b[0],...,xmm0.b[3],
|
| + ; respectively.
|
| + CALC_B xmm0, xmm1, 4
|
| +
|
| + ; Interleave r[0],...,r[3], g[0],...,g[3], and b[0],...,b[3] to create four
|
| + ; ARGB pixels
|
| + movd xmm1, TEMPd
|
| + PACK_ARGB xmm0, xmm2, xmm1
|
| +
|
| +%if PIXELSIZE == 4
|
| + movdqu DQWORD [ARGBq + WIDTHq * 4 * 2], xmm0
|
| +%else
|
| + ; Pack four ARGB pixels to four RGB pixels.
|
| + PACK_RGB xmm0, 12
|
| + PACK_RGB xmm0, 8
|
| + PACK_RGB xmm0, 4
|
| +
|
| + mov TEMPq, WIDTHq
|
| + lea TEMPq, [TEMPq + TEMPq * 2]
|
| + movq QWORD [ARGBq + TEMPq * 2], xmm0
|
| + psrldq xmm0, 8
|
| + movd DWORD [ARGBq + TEMPq * 2 + 8], xmm0
|
| +%endif
|
| +
|
| + test WIDTHq, WIDTHq
|
| + jnz .convert_four_pixels_unaligned
|
| +
|
| +.convert_finish:
|
| + ; Just exit this function since this is a void function.
|
| + RET
|
|
|