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

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

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.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

Powered by Google App Engine
This is Rietveld 408576698