| OLD | NEW |
| (Empty) | |
| 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. |
| 4 |
| 5 ; |
| 6 ; void SYMBOL(const uint8* y, |
| 7 ; const uint8* u, |
| 8 ; const uint8* v, |
| 9 ; uint8* argb, |
| 10 ; int width); |
| 11 ; |
| 12 ; Converts a row of YUV (4:1:1) pixels to the ARGB (RGB) colorspace. This |
| 13 ; function reads YUV pixels from right to left, convert their colorspace to ARGB |
| 14 ; (RGB), and write the converted pixels to the output buffers. The following |
| 15 ; code snippet represents the rough structure of this fucntion. |
| 16 ; |
| 17 ; if (width & 1) { |
| 18 ; --width; |
| 19 ; convert_one_pixel(y, u, v, argb, width); |
| 20 ; } |
| 21 ; if (width & 2) { |
| 22 ; width -= 2; |
| 23 ; convert_two_pixels(y, u, v, argb, width); |
| 24 ; } |
| 25 ; while (width) { |
| 26 ; width -= 4; |
| 27 ; convert_four_pixels(y, u, v, argb, width); |
| 28 ; } |
| 29 ; |
| 30 ; This function has pseudo-code snippets to describe its behaviors. For |
| 31 ; simplicity, they use the following notations. |
| 32 ; |
| 33 ; #define Y(n) y[n] - 16 |
| 34 ; #define U(n) u[n] - 128 |
| 35 ; #define V(n) v[n] - 128 |
| 36 ; #define FIX(n) (n * (1 << SHIFT_BITS) * 0.5) |
| 37 ; #define ToByte(n) ((n < 0) ? 0 : (n > 255 ? 255 : n)) |
| 38 ; |
| 39 ; union { |
| 40 ; int32 d[4]; |
| 41 ; int16 w[8]; |
| 42 ; int8 b[16]; |
| 43 ; } xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 |
| 44 ; |
| 45 ; |
| 46 global SYMBOL PRIVATE |
| 47 align function_align |
| 48 |
| 49 SYMBOL: |
| 50 %assign stack_offset 0 |
| 51 PROLOGUE 5, 6, 8, Y, U, V, ARGB, WIDTH, TEMP |
| 52 |
| 53 ; Initialize constants used in this function. |
| 54 LOAD_SYM TEMPq, SIMD_ConvertYUVtoARGB_kTable |
| 55 movdqa xmm0, DQWORD [TEMPq + 0] |
| 56 movdqa xmm1, DQWORD [TEMPq + 16] |
| 57 pshufd XMM_CONST_BIAS, xmm0, 01000100B |
| 58 pshufd XMM_CONST_R, xmm0, 11101110B |
| 59 pshufd XMM_CONST_G, xmm1, 01000100B |
| 60 pshufd XMM_CONST_B, xmm1, 11101110B |
| 61 |
| 62 .convert_one_pixel: |
| 63 ; Divide the input width by two so it represents the offsets for u[] and v[]. |
| 64 ; When the width is odd, We read the rightmost ARGB pixel and convert its |
| 65 ; colorspace to YUV. This code stores one Y pixel, one U pixel, and one V |
| 66 ; pixel. |
| 67 sar WIDTHq, 1 |
| 68 jnc .convert_two_pixels |
| 69 |
| 70 ; Read one Y pixel, one U pixel, and one V pixel. It packs the pixels into |
| 71 ; xmm0. |
| 72 READ_YUV 1 |
| 73 |
| 74 ; Calculate r[0]. |
| 75 movdqa xmm2, xmm0 |
| 76 CALC_R xmm2, xmm3, 1 |
| 77 movd TEMPd, xmm2 |
| 78 |
| 79 ; Calculate g[0]. |
| 80 movdqa xmm2, xmm0 |
| 81 CALC_G xmm2, xmm3, 1 |
| 82 |
| 83 ; Calculate b[0]. |
| 84 CALC_B xmm0, xmm1, 1 |
| 85 |
| 86 ; Interleave r[0], g[0], and b[0] to create one ARGB pixel. |
| 87 movd xmm1, TEMPd |
| 88 PACK_ARGB xmm0, xmm2, xmm1 |
| 89 |
| 90 %if PIXELSIZE == 4 |
| 91 movd DWORD [ARGBq + WIDTHq * 4 * 2], xmm0 |
| 92 %else |
| 93 MOVq xmm1, WIDTHq |
| 94 lea WIDTHq, [WIDTHq + WIDTHq * 2] |
| 95 movd TEMPd, xmm0 |
| 96 mov WORD [ARGBq + WIDTHq * 2], TEMPw |
| 97 sar TEMPw, 16 |
| 98 mov BYTE [ARGBq + WIDTHq * 2 + 2], TEMPb |
| 99 MOVq WIDTHq, xmm1 |
| 100 %endif |
| 101 |
| 102 .convert_two_pixels: |
| 103 ; When the input width is not a multiple of four, we read the rightmost two Y |
| 104 ; pixels, one U pixel, and one V pixel to convert their colorspace to RGB. |
| 105 ; This code stores two RGBA pixels. |
| 106 test WIDTHb, 1 |
| 107 jz .convert_four_pixels |
| 108 sub WIDTHq, 2 / 2 |
| 109 |
| 110 ; Read two Y pixels, one U pixels, and one V pixels to xmm0. |
| 111 READ_YUV 2 |
| 112 |
| 113 ; Calculate r[0] and r[0]. |
| 114 movdqa xmm2, xmm0 |
| 115 CALC_R xmm2, xmm3, 1 |
| 116 movd TEMPd, xmm2 |
| 117 |
| 118 ; Calculate g[0]. |
| 119 movdqa xmm2, xmm0 |
| 120 CALC_G xmm2, xmm3, 1 |
| 121 |
| 122 ; Calculate b[0]. |
| 123 CALC_B xmm0, xmm1, 1 |
| 124 |
| 125 ; Interleave r[0], g[0], and b[0] to create one ARGB pixel. |
| 126 movd xmm1, TEMPd |
| 127 PACK_ARGB xmm0, xmm2, xmm1 |
| 128 |
| 129 %if PIXELSIZE == 4 |
| 130 movq QWORD [ARGBq + WIDTHq * 4 * 2], xmm0 |
| 131 %else |
| 132 MOVq xmm1, WIDTHq |
| 133 lea WIDTHq, [WIDTHq + WIDTHq * 2] |
| 134 movd DWORD [ARGBq + WIDTHq * 2], xmm0 |
| 135 psrldq xmm0, 4 |
| 136 movd TEMPd, xmm0 |
| 137 mov WORD [ARGBq + WIDTHq * 2 + 4], TEMPw |
| 138 MOVq WIDTHq, xmm1 |
| 139 %endif |
| 140 |
| 141 .convert_four_pixels: |
| 142 ; Read four Y pixels, two U pixels, and two V pixels to convert their |
| 143 ; colorspace to RGB. This code stores four RGBA (or RGB) pixels. |
| 144 test WIDTHq, WIDTHq |
| 145 jz .convert_finish |
| 146 |
| 147 %if PIXELSIZE == 4 |
| 148 ; Check if the input buffer is aligned to a 16-byte boundary so we can use |
| 149 ; movdqa for writing the ARGB pixels if possible. |
| 150 test ARGBw, 15 |
| 151 jnz .convert_four_pixels_unaligned |
| 152 |
| 153 .convert_four_pixels_aligned: |
| 154 sub WIDTHq, 4 / 2 |
| 155 |
| 156 ; Read four Y pixels, two U pixels, and two V pixels to xmm0 and xmm1. |
| 157 READ_YUV 4 |
| 158 |
| 159 ; Calculate r[0],...,r[3]. It saves the results to TEMP.b[0],...,TEMP.b[3], |
| 160 ; respecitively. |
| 161 movdqa xmm2, xmm0 |
| 162 movdqa xmm3, xmm1 |
| 163 CALC_R xmm2, xmm3, 4 |
| 164 movd TEMPd, xmm2 |
| 165 |
| 166 ; Calculate g[0],...,g[3]. It saves the results to xmm2.b[0],...,xmm2.b[3], |
| 167 ; respectively. |
| 168 movdqa xmm2, xmm0 |
| 169 movdqa xmm3, xmm1 |
| 170 CALC_G xmm2, xmm3, 4 |
| 171 |
| 172 ; Calculate b[0],...,b[3]. It saves the results to xmm0.b[0],...,xmm0.b[3], |
| 173 ; respectively. |
| 174 CALC_B xmm0, xmm1, 4 |
| 175 |
| 176 ; Interleave r[0],...,r[3], g[0],...,g[3], and b[0],...,b[3] to create four |
| 177 ; ARGB pixels |
| 178 movd xmm1, TEMPd |
| 179 PACK_ARGB xmm0, xmm2, xmm1 |
| 180 |
| 181 ; Write four ARGB pixels. (We can use movdqa here since we have checked if the |
| 182 ; destination address is aligned.) |
| 183 movdqa DQWORD [ARGBq + WIDTHq * 4 * 2], xmm0 |
| 184 |
| 185 test WIDTHq, WIDTHq |
| 186 jnz .convert_four_pixels_aligned |
| 187 |
| 188 jmp .convert_finish |
| 189 %endif ; PIXELSIZE == 4 |
| 190 |
| 191 .convert_four_pixels_unaligned: |
| 192 sub WIDTHq, 4 / 2 |
| 193 |
| 194 ; Read four Y pixels, two U pixels, and two V pixels to xmm0 and xmm1. |
| 195 READ_YUV 4 |
| 196 |
| 197 ; Calculate r[0],...,r[3]. It saves the results to TEMP.b[0],...,TEMP.b[3], |
| 198 ; respecitively. |
| 199 movdqa xmm2, xmm0 |
| 200 movdqa xmm3, xmm1 |
| 201 CALC_R xmm2, xmm3, 4 |
| 202 movd TEMPd, xmm2 |
| 203 |
| 204 ; Calculate g[0],...,g[3]. It saves the results to xmm2.b[0],...,xmm2.b[3], |
| 205 ; respectively. |
| 206 movdqa xmm2, xmm0 |
| 207 movdqa xmm3, xmm1 |
| 208 CALC_G xmm2, xmm3, 4 |
| 209 |
| 210 ; Calculate b[0],...,b[3]. It saves the results to xmm0.b[0],...,xmm0.b[3], |
| 211 ; respectively. |
| 212 CALC_B xmm0, xmm1, 4 |
| 213 |
| 214 ; Interleave r[0],...,r[3], g[0],...,g[3], and b[0],...,b[3] to create four |
| 215 ; ARGB pixels |
| 216 movd xmm1, TEMPd |
| 217 PACK_ARGB xmm0, xmm2, xmm1 |
| 218 |
| 219 %if PIXELSIZE == 4 |
| 220 movdqu DQWORD [ARGBq + WIDTHq * 4 * 2], xmm0 |
| 221 %else |
| 222 ; Pack four ARGB pixels to four RGB pixels. |
| 223 PACK_RGB xmm0, 12 |
| 224 PACK_RGB xmm0, 8 |
| 225 PACK_RGB xmm0, 4 |
| 226 |
| 227 mov TEMPq, WIDTHq |
| 228 lea TEMPq, [TEMPq + TEMPq * 2] |
| 229 movq QWORD [ARGBq + TEMPq * 2], xmm0 |
| 230 psrldq xmm0, 8 |
| 231 movd DWORD [ARGBq + TEMPq * 2 + 8], xmm0 |
| 232 %endif |
| 233 |
| 234 test WIDTHq, WIDTHq |
| 235 jnz .convert_four_pixels_unaligned |
| 236 |
| 237 .convert_finish: |
| 238 ; Just exit this function since this is a void function. |
| 239 RET |
| OLD | NEW |