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

Unified Diff: media/base/simd/convert_rgb_to_yuv_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, 3 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_rgb_to_yuv_ssse3.inc
===================================================================
--- media/base/simd/convert_rgb_to_yuv_ssse3.inc (revision 0)
+++ media/base/simd/convert_rgb_to_yuv_ssse3.inc (revision 0)
@@ -0,0 +1,200 @@
+; 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* argb, uint8* y, uint8* u, uint8* v, int width);
+;
+; The main code that converts RGB pixels to YUV pixels. This function roughly
+; consists of three parts: converting one ARGB pixel to YUV pixels, converting
+; two ARGB pixels to YUV pixels, and converting four ARGB pixels to YUV pixels.
+; To write the structure of this function in C, it becomes the snippet listed
+; below.
+;
+; if (width & 1) {
+; --width;
+; // Convert one ARGB pixel to one Y pixel, one U pixel, and one V pixel.
+; }
+;
+; if (width & 2) {
+; width -= 2;
+; // Convert two ARGB pixels to two Y pixels, one U pixel, and one V pixel.
+; }
+;
+; while (width) {
+; width -= 4;
+; // Convert four ARGB pixels to four Y pixels, two U pixels, and two V
+; // pixels.
+; }
+;
+ global mangle(SYMBOL) PRIVATE
+ align function_align
+
+mangle(SYMBOL):
+ %assign stack_offset 0
+ PROLOGUE 5, 6, 8, ARGB, Y, U, V, WIDTH, TEMP
+
+ ; Initialize constants used in this function. (We use immediates to avoid
+ ; dependency onto GOT.)
+ LOAD_XMM XMM_CONST_Y0, 0x00420219
+ LOAD_XMM XMM_CONST_Y1, 0x00007F00
+ LOAD_XMM XMM_CONST_U, 0x00DAB670
+ LOAD_XMM XMM_CONST_V, 0x0070A2EE
+ LOAD_XMM XMM_CONST_128, 0x00800080
+
+.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 ARGB (or RGB) pixel.
+ READ_ARGB xmm0, 1
+
+ ; Calculate y[0] from one RGB pixel read above.
+ CALC_Y xmm1, xmm0
+ movd TEMPd, xmm1
+ mov BYTE [Yq + WIDTHq * 2], TEMPb
+
+ ; Calculate u[0] from one RGB pixel read above. If this is an odd line, the
+ ; output pixel contains the U value calculated in the previous call. We also
+ ; read this pixel and calculate their average.
+ INIT_UV TEMPd, Uq, 4
+ CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
+ movd TEMPd, xmm1
+ mov BYTE [Uq + WIDTHq], TEMPb
+
+ ; Calculate v[0] from one RGB pixel. Same as u[0], we read the result of the
+ ; previous call and get their average.
+ INIT_UV TEMPd, Uq, 4
+ CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
+ movd TEMPd, xmm1
+ mov BYTE [Vq + WIDTHq], TEMPb
+
+.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 WIDTHb, 2 / 2
+ jz .convert_four_pixels
+ sub WIDTHb, 2 / 2
+
+ ; Read two ARGB (or RGB) pixels.
+ READ_ARGB xmm0, 2
+
+ ; Calculate r[0] and r[1] from two RGB pixels read above.
+ CALC_Y xmm1, xmm0
+ movd TEMPd, xmm1
+ mov WORD [Yq + WIDTHq * 2], TEMPw
+
+ ; Skip calculating u and v if the output buffer is NULL.
+ test Uq, Uq
+ jz .convert_four_pixels
+
+ ; Calculate u[0] from two RGB pixels read above. (For details, read the above
+ ; comment in .convert_one_pixel).
+ INIT_UV TEMPd, Uq, 2
+ CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
+ movd TEMPd, xmm1
+ mov BYTE [Uq + WIDTHq], TEMPb
+
+ ; Calculate v[0] from two RGB pixels read above.
+ INIT_UV TEMPd, Vq, 2
+ CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
+ movd TEMPd, xmm1
+ mov BYTE [Vq + WIDTHq], TEMPb
+
+.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 WIDTHq, WIDTHq
+ jz .convert_finish
+
+%if PIXELSIZE == 4
+ ; Check if the input buffer is aligned to a 16-byte boundary and use movdqa
+ ; for reading the ARGB pixels.
+ test ARGBw, 15
+ jnz .convert_four_pixels_unaligned
+
+.convert_four_pixels_aligned:
+ sub WIDTHq, 4 / 2
+
+ ; Read four ARGB pixels. (We can use movdqa here since we have checked if the
+ ; source address is aligned.)
+ movdqa xmm0, DQWORD [ARGBq + WIDTHq * 4 * 2]
+
+ ; Calculate y[0], y[1], y[2],and, y[3] from the input ARGB pixels.
+ CALC_Y xmm1, xmm0
+ movd DWORD [Yq + WIDTHq * 2], xmm1
+
+%if SUBSAMPLING == 0
+ ; Skip calculating u and v if the output buffer is NULL, which means we are
+ ; converting an odd line. (When we enable subsampling, these buffers must
+ ; contain the u and v values for the previous call, i.e. these variables must
+ ; not be NULL.)
+ test Uq, Uq
+ jz .convert_four_pixels_aligned_next
+%endif
+
+ ; Calculate u[0] and u[1] from four ARGB pixels read above.
+ INIT_UV TEMPd, Uq, 4
+ CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
+ movd TEMPd, xmm1
+ mov WORD [Uq + WIDTHq], TEMPw
+
+ ; Calculate v[0] and v[1] from four ARGB pixels read above.
+ INIT_UV TEMPd, Vq, 4
+ CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
+ movd TEMPd, xmm1
+ mov WORD [Vq + WIDTHq], TEMPw
+
+%if SUBSAMPLING == 0
+.convert_four_pixels_aligned_next:
+%endif
+
+ test WIDTHq, WIDTHq
+ jnz .convert_four_pixels_aligned
+
+ jmp .convert_finish
+%endif
+
+.convert_four_pixels_unaligned:
+ sub WIDTHq, 4 / 2
+
+ ; Read four ARGB (or RGB) pixels.
+ READ_ARGB xmm0, 4
+
+ ; Calculate y[0], y[1], y[2],and, y[3] from the input ARGB pixels.
+ CALC_Y xmm1, xmm0
+ movd DWORD [Yq + WIDTHq * 2], xmm1
+
+%if SUBSAMPLING == 0
+ ; Skip calculating u and v if the output buffer is NULL.
+ test Uq, Uq
+ jz .convert_four_pixels_unaligned_next
+%endif
+
+ ; Calculate u[0] and u[1] from the input ARGB pixels.
+ INIT_UV TEMPd, Uq, 4
+ CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
+ movd TEMPd, xmm1
+ mov WORD [Uq + WIDTHq], TEMPw
+
+ ; Calculate v[0] and v[1] from the input ARGB pixels.
+ INIT_UV TEMPd, Vq, 4
+ CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
+ movd TEMPd, xmm1
+ mov WORD [Vq + WIDTHq], TEMPw
+
+%if SUBSAMPLING == 0
+.convert_four_pixels_unaligned_next:
+%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