1 ; Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 ; Use of this source code is governed by a BSD-style license that can be
3 ; found in the LICENSE file.
6 ; void SYMBOL(const uint8* argb, uint8* y, uint8* u, uint8* v, int width);
8 ; The main code that converts RGB pixels to YUV pixels. This function roughly
9 ; consists of three parts: converting one ARGB pixel to YUV pixels, converting
10 ; two ARGB pixels to YUV pixels, and converting four ARGB pixels to YUV pixels.
11 ; To write the structure of this function in C, it becomes the snippet listed
16 ; // Convert one ARGB pixel to one Y pixel, one U pixel, and one V pixel.
21 ; // Convert two ARGB pixels to two Y pixels, one U pixel, and one V pixel.
26 ; // Convert four ARGB pixels to four Y pixels, two U pixels, and two V
34 %assign stack_offset 0
35 PROLOGUE 5, 6, 8, ARGB, Y, U, V, WIDTH, TEMP
37 ; Initialize constants used in this function. (We use immediates to avoid
38 ; dependency onto GOT.)
39 LOAD_XMM XMM_CONST_Y0, 0x00420219
40 LOAD_XMM XMM_CONST_Y1, 0x00007F00
41 LOAD_XMM XMM_CONST_U, 0x00DAB670
42 LOAD_XMM XMM_CONST_V, 0x0070A2EE
43 LOAD_XMM XMM_CONST_128, 0x00800080
46 ; Divide the input width by two so it represents the offsets for u[] and v[].
47 ; When the width is odd, We read the rightmost ARGB pixel and convert its
48 ; colorspace to YUV. This code stores one Y pixel, one U pixel, and one V
51 jnc .convert_two_pixels
53 ; Read one ARGB (or RGB) pixel.
56 ; Calculate y[0] from one RGB pixel read above.
59 mov BYTE [Yq + WIDTHq * 2], TEMPb
61 ; Calculate u[0] from one RGB pixel read above. If this is an odd line, the
62 ; output pixel contains the U value calculated in the previous call. We also
63 ; read this pixel and calculate their average.
65 CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
67 mov BYTE [Uq + WIDTHq], TEMPb
69 ; Calculate v[0] from one RGB pixel. Same as u[0], we read the result of the
70 ; previous call and get their average.
72 CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
74 mov BYTE [Vq + WIDTHq], TEMPb
77 ; If the input width is not a multiple of four, read the rightmost two ARGB
78 ; pixels and convert their colorspace to YUV. This code stores two Y pixels,
79 ; one U pixel, and one V pixel.
81 jz .convert_four_pixels
84 ; Read two ARGB (or RGB) pixels.
87 ; Calculate r[0] and r[1] from two RGB pixels read above.
90 mov WORD [Yq + WIDTHq * 2], TEMPw
92 ; Skip calculating u and v if the output buffer is NULL.
94 jz .convert_four_pixels
96 ; Calculate u[0] from two RGB pixels read above. (For details, read the above
97 ; comment in .convert_one_pixel).
99 CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
101 mov BYTE [Uq + WIDTHq], TEMPb
103 ; Calculate v[0] from two RGB pixels read above.
105 CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
107 mov BYTE [Vq + WIDTHq], TEMPb
109 .convert_four_pixels:
110 ; Read four ARGB pixels and convert their colorspace to YUV. This code stores
111 ; four Y pixels, two U pixels, and two V pixels.
116 ; Check if the input buffer is aligned to a 16-byte boundary and use movdqa
117 ; for reading the ARGB pixels.
119 jnz .convert_four_pixels_unaligned
121 .convert_four_pixels_aligned:
124 ; Read four ARGB pixels. (We can use movdqa here since we have checked if the
125 ; source address is aligned.)
126 movdqa xmm0, DQWORD [ARGBq + WIDTHq * 4 * 2]
128 ; Calculate y[0], y[1], y[2],and, y[3] from the input ARGB pixels.
130 movd DWORD [Yq + WIDTHq * 2], xmm1
133 ; Skip calculating u and v if the output buffer is NULL, which means we are
134 ; converting an odd line. (When we enable subsampling, these buffers must
135 ; contain the u and v values for the previous call, i.e. these variables must
138 jz .convert_four_pixels_aligned_next
141 ; Calculate u[0] and u[1] from four ARGB pixels read above.
143 CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
145 mov WORD [Uq + WIDTHq], TEMPw
147 ; Calculate v[0] and v[1] from four ARGB pixels read above.
149 CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
151 mov WORD [Vq + WIDTHq], TEMPw
154 .convert_four_pixels_aligned_next:
158 jnz .convert_four_pixels_aligned
163 .convert_four_pixels_unaligned:
166 ; Read four ARGB (or RGB) pixels.
169 ; Calculate y[0], y[1], y[2],and, y[3] from the input ARGB pixels.
171 movd DWORD [Yq + WIDTHq * 2], xmm1
174 ; Skip calculating u and v if the output buffer is NULL.
176 jz .convert_four_pixels_unaligned_next
179 ; Calculate u[0] and u[1] from the input ARGB pixels.
181 CALC_UV xmm1, xmm0, XMM_CONST_U, TEMPd
183 mov WORD [Uq + WIDTHq], TEMPw
185 ; Calculate v[0] and v[1] from the input ARGB pixels.
187 CALC_UV xmm1, xmm0, XMM_CONST_V, TEMPd
189 mov WORD [Vq + WIDTHq], TEMPw
192 .convert_four_pixels_unaligned_next:
196 jnz .convert_four_pixels_unaligned
199 ; Just exit this function since this is a void function.