1/*
2 *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS. All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <stdlib.h>
12#include <time.h>
13
14#include "libyuv/compare.h"
15#include "libyuv/convert.h"
16#include "libyuv/convert_argb.h"
17#include "libyuv/convert_from.h"
18#include "libyuv/convert_from_argb.h"
19#include "libyuv/cpu_id.h"
20#include "libyuv/format_conversion.h"
21#include "libyuv/planar_functions.h"
22#include "libyuv/rotate.h"
23#include "libyuv/row.h"  // For Sobel
24#include "../unit_test/unit_test.h"
25
26#if defined(_MSC_VER)
27#define SIMD_ALIGNED(var) __declspec(align(16)) var
28#else  // __GNUC__
29#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
30#endif
31
32namespace libyuv {
33
34TEST_F(libyuvTest, TestAttenuate) {
35  const int kSize = 1280 * 4;
36  align_buffer_64(orig_pixels, kSize);
37  align_buffer_64(atten_pixels, kSize);
38  align_buffer_64(unatten_pixels, kSize);
39  align_buffer_64(atten2_pixels, kSize);
40
41  // Test unattenuation clamps
42  orig_pixels[0 * 4 + 0] = 200u;
43  orig_pixels[0 * 4 + 1] = 129u;
44  orig_pixels[0 * 4 + 2] = 127u;
45  orig_pixels[0 * 4 + 3] = 128u;
46  // Test unattenuation transparent and opaque are unaffected
47  orig_pixels[1 * 4 + 0] = 16u;
48  orig_pixels[1 * 4 + 1] = 64u;
49  orig_pixels[1 * 4 + 2] = 192u;
50  orig_pixels[1 * 4 + 3] = 0u;
51  orig_pixels[2 * 4 + 0] = 16u;
52  orig_pixels[2 * 4 + 1] = 64u;
53  orig_pixels[2 * 4 + 2] = 192u;
54  orig_pixels[2 * 4 + 3] = 255u;
55  orig_pixels[3 * 4 + 0] = 16u;
56  orig_pixels[3 * 4 + 1] = 64u;
57  orig_pixels[3 * 4 + 2] = 192u;
58  orig_pixels[3 * 4 + 3] = 128u;
59  ARGBUnattenuate(orig_pixels, 0, unatten_pixels, 0, 4, 1);
60  EXPECT_EQ(255u, unatten_pixels[0 * 4 + 0]);
61  EXPECT_EQ(255u, unatten_pixels[0 * 4 + 1]);
62  EXPECT_EQ(254u, unatten_pixels[0 * 4 + 2]);
63  EXPECT_EQ(128u, unatten_pixels[0 * 4 + 3]);
64  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 0]);
65  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 1]);
66  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 2]);
67  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 3]);
68  EXPECT_EQ(16u, unatten_pixels[2 * 4 + 0]);
69  EXPECT_EQ(64u, unatten_pixels[2 * 4 + 1]);
70  EXPECT_EQ(192u, unatten_pixels[2 * 4 + 2]);
71  EXPECT_EQ(255u, unatten_pixels[2 * 4 + 3]);
72  EXPECT_EQ(32u, unatten_pixels[3 * 4 + 0]);
73  EXPECT_EQ(128u, unatten_pixels[3 * 4 + 1]);
74  EXPECT_EQ(255u, unatten_pixels[3 * 4 + 2]);
75  EXPECT_EQ(128u, unatten_pixels[3 * 4 + 3]);
76
77  for (int i = 0; i < 1280; ++i) {
78    orig_pixels[i * 4 + 0] = i;
79    orig_pixels[i * 4 + 1] = i / 2;
80    orig_pixels[i * 4 + 2] = i / 3;
81    orig_pixels[i * 4 + 3] = i;
82  }
83  ARGBAttenuate(orig_pixels, 0, atten_pixels, 0, 1280, 1);
84  ARGBUnattenuate(atten_pixels, 0, unatten_pixels, 0, 1280, 1);
85  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
86    ARGBAttenuate(unatten_pixels, 0, atten2_pixels, 0, 1280, 1);
87  }
88  for (int i = 0; i < 1280; ++i) {
89    EXPECT_NEAR(atten_pixels[i * 4 + 0], atten2_pixels[i * 4 + 0], 2);
90    EXPECT_NEAR(atten_pixels[i * 4 + 1], atten2_pixels[i * 4 + 1], 2);
91    EXPECT_NEAR(atten_pixels[i * 4 + 2], atten2_pixels[i * 4 + 2], 2);
92    EXPECT_NEAR(atten_pixels[i * 4 + 3], atten2_pixels[i * 4 + 3], 2);
93  }
94  // Make sure transparent, 50% and opaque are fully accurate.
95  EXPECT_EQ(0, atten_pixels[0 * 4 + 0]);
96  EXPECT_EQ(0, atten_pixels[0 * 4 + 1]);
97  EXPECT_EQ(0, atten_pixels[0 * 4 + 2]);
98  EXPECT_EQ(0, atten_pixels[0 * 4 + 3]);
99  EXPECT_EQ(64, atten_pixels[128 * 4 + 0]);
100  EXPECT_EQ(32, atten_pixels[128 * 4 + 1]);
101  EXPECT_EQ(21,  atten_pixels[128 * 4 + 2]);
102  EXPECT_EQ(128, atten_pixels[128 * 4 + 3]);
103  EXPECT_NEAR(255, atten_pixels[255 * 4 + 0], 1);
104  EXPECT_NEAR(127, atten_pixels[255 * 4 + 1], 1);
105  EXPECT_NEAR(85,  atten_pixels[255 * 4 + 2], 1);
106  EXPECT_EQ(255, atten_pixels[255 * 4 + 3]);
107
108  free_aligned_buffer_64(atten2_pixels);
109  free_aligned_buffer_64(unatten_pixels);
110  free_aligned_buffer_64(atten_pixels);
111  free_aligned_buffer_64(orig_pixels);
112}
113
114static int TestAttenuateI(int width, int height, int benchmark_iterations,
115                          int invert, int off) {
116  if (width < 1) {
117    width = 1;
118  }
119  const int kBpp = 4;
120  const int kStride = (width * kBpp + 15) & ~15;
121  align_buffer_64(src_argb, kStride * height + off);
122  align_buffer_64(dst_argb_c, kStride * height);
123  align_buffer_64(dst_argb_opt, kStride * height);
124  srandom(time(NULL));
125  for (int i = 0; i < kStride * height; ++i) {
126    src_argb[i + off] = (random() & 0xff);
127  }
128  memset(dst_argb_c, 0, kStride * height);
129  memset(dst_argb_opt, 0, kStride * height);
130
131  MaskCpuFlags(0);
132  ARGBAttenuate(src_argb + off, kStride,
133                dst_argb_c, kStride,
134                width, invert * height);
135  MaskCpuFlags(-1);
136  for (int i = 0; i < benchmark_iterations; ++i) {
137    ARGBAttenuate(src_argb + off, kStride,
138                  dst_argb_opt, kStride,
139                  width, invert * height);
140  }
141  int max_diff = 0;
142  for (int i = 0; i < kStride * height; ++i) {
143    int abs_diff =
144        abs(static_cast<int>(dst_argb_c[i]) -
145            static_cast<int>(dst_argb_opt[i]));
146    if (abs_diff > max_diff) {
147      max_diff = abs_diff;
148    }
149  }
150  free_aligned_buffer_64(src_argb);
151  free_aligned_buffer_64(dst_argb_c);
152  free_aligned_buffer_64(dst_argb_opt);
153  return max_diff;
154}
155
156TEST_F(libyuvTest, ARGBAttenuate_Any) {
157  int max_diff = TestAttenuateI(benchmark_width_ - 1, benchmark_height_,
158                                benchmark_iterations_, +1, 0);
159  EXPECT_LE(max_diff, 2);
160}
161
162TEST_F(libyuvTest, ARGBAttenuate_Unaligned) {
163  int max_diff = TestAttenuateI(benchmark_width_, benchmark_height_,
164                                benchmark_iterations_, +1, 1);
165  EXPECT_LE(max_diff, 2);
166}
167
168TEST_F(libyuvTest, ARGBAttenuate_Invert) {
169  int max_diff = TestAttenuateI(benchmark_width_, benchmark_height_,
170                                benchmark_iterations_, -1, 0);
171  EXPECT_LE(max_diff, 2);
172}
173
174TEST_F(libyuvTest, ARGBAttenuate_Opt) {
175  int max_diff = TestAttenuateI(benchmark_width_, benchmark_height_,
176                                benchmark_iterations_, +1, 0);
177  EXPECT_LE(max_diff, 2);
178}
179
180static int TestUnattenuateI(int width, int height, int benchmark_iterations,
181                            int invert, int off) {
182  if (width < 1) {
183    width = 1;
184  }
185  const int kBpp = 4;
186  const int kStride = (width * kBpp + 15) & ~15;
187  align_buffer_64(src_argb, kStride * height + off);
188  align_buffer_64(dst_argb_c, kStride * height);
189  align_buffer_64(dst_argb_opt, kStride * height);
190  srandom(time(NULL));
191  for (int i = 0; i < kStride * height; ++i) {
192    src_argb[i + off] = (random() & 0xff);
193  }
194  ARGBAttenuate(src_argb + off, kStride,
195                src_argb + off, kStride,
196                width, height);
197  memset(dst_argb_c, 0, kStride * height);
198  memset(dst_argb_opt, 0, kStride * height);
199
200  MaskCpuFlags(0);
201  ARGBUnattenuate(src_argb + off, kStride,
202                  dst_argb_c, kStride,
203                  width, invert * height);
204  MaskCpuFlags(-1);
205  for (int i = 0; i < benchmark_iterations; ++i) {
206    ARGBUnattenuate(src_argb + off, kStride,
207                    dst_argb_opt, kStride,
208                    width, invert * height);
209  }
210  int max_diff = 0;
211  for (int i = 0; i < kStride * height; ++i) {
212    int abs_diff =
213        abs(static_cast<int>(dst_argb_c[i]) -
214            static_cast<int>(dst_argb_opt[i]));
215    if (abs_diff > max_diff) {
216      max_diff = abs_diff;
217    }
218  }
219  free_aligned_buffer_64(src_argb);
220  free_aligned_buffer_64(dst_argb_c);
221  free_aligned_buffer_64(dst_argb_opt);
222  return max_diff;
223}
224
225TEST_F(libyuvTest, ARGBUnattenuate_Any) {
226  int max_diff = TestUnattenuateI(benchmark_width_ - 1, benchmark_height_,
227                                  benchmark_iterations_, +1, 0);
228  EXPECT_LE(max_diff, 2);
229}
230
231TEST_F(libyuvTest, ARGBUnattenuate_Unaligned) {
232  int max_diff = TestUnattenuateI(benchmark_width_, benchmark_height_,
233                                  benchmark_iterations_, +1, 1);
234  EXPECT_LE(max_diff, 2);
235}
236
237TEST_F(libyuvTest, ARGBUnattenuate_Invert) {
238  int max_diff = TestUnattenuateI(benchmark_width_, benchmark_height_,
239                                  benchmark_iterations_, -1, 0);
240  EXPECT_LE(max_diff, 2);
241}
242
243TEST_F(libyuvTest, ARGBUnattenuate_Opt) {
244  int max_diff = TestUnattenuateI(benchmark_width_, benchmark_height_,
245                                  benchmark_iterations_, +1, 0);
246  EXPECT_LE(max_diff, 2);
247}
248
249TEST_F(libyuvTest, TestARGBComputeCumulativeSum) {
250  SIMD_ALIGNED(uint8 orig_pixels[16][16][4]);
251  SIMD_ALIGNED(int32 added_pixels[16][16][4]);
252
253  for (int y = 0; y < 16; ++y) {
254    for (int x = 0; x < 16; ++x) {
255      orig_pixels[y][x][0] = 1u;
256      orig_pixels[y][x][1] = 2u;
257      orig_pixels[y][x][2] = 3u;
258      orig_pixels[y][x][3] = 255u;
259    }
260  }
261
262  ARGBComputeCumulativeSum(&orig_pixels[0][0][0], 16 * 4,
263                           &added_pixels[0][0][0], 16 * 4,
264                           16, 16);
265
266  for (int y = 0; y < 16; ++y) {
267    for (int x = 0; x < 16; ++x) {
268      EXPECT_EQ((x + 1) * (y + 1), added_pixels[y][x][0]);
269      EXPECT_EQ((x + 1) * (y + 1) * 2, added_pixels[y][x][1]);
270      EXPECT_EQ((x + 1) * (y + 1) * 3, added_pixels[y][x][2]);
271      EXPECT_EQ((x + 1) * (y + 1) * 255, added_pixels[y][x][3]);
272    }
273  }
274}
275
276TEST_F(libyuvTest, TestARGBGray) {
277  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
278  memset(orig_pixels, 0, sizeof(orig_pixels));
279
280  // Test blue
281  orig_pixels[0][0] = 255u;
282  orig_pixels[0][1] = 0u;
283  orig_pixels[0][2] = 0u;
284  orig_pixels[0][3] = 128u;
285  // Test green
286  orig_pixels[1][0] = 0u;
287  orig_pixels[1][1] = 255u;
288  orig_pixels[1][2] = 0u;
289  orig_pixels[1][3] = 0u;
290  // Test red
291  orig_pixels[2][0] = 0u;
292  orig_pixels[2][1] = 0u;
293  orig_pixels[2][2] = 255u;
294  orig_pixels[2][3] = 255u;
295  // Test black
296  orig_pixels[3][0] = 0u;
297  orig_pixels[3][1] = 0u;
298  orig_pixels[3][2] = 0u;
299  orig_pixels[3][3] = 255u;
300  // Test white
301  orig_pixels[4][0] = 255u;
302  orig_pixels[4][1] = 255u;
303  orig_pixels[4][2] = 255u;
304  orig_pixels[4][3] = 255u;
305  // Test color
306  orig_pixels[5][0] = 16u;
307  orig_pixels[5][1] = 64u;
308  orig_pixels[5][2] = 192u;
309  orig_pixels[5][3] = 224u;
310  // Do 16 to test asm version.
311  ARGBGray(&orig_pixels[0][0], 0, 0, 0, 16, 1);
312  EXPECT_EQ(30u, orig_pixels[0][0]);
313  EXPECT_EQ(30u, orig_pixels[0][1]);
314  EXPECT_EQ(30u, orig_pixels[0][2]);
315  EXPECT_EQ(128u, orig_pixels[0][3]);
316  EXPECT_EQ(149u, orig_pixels[1][0]);
317  EXPECT_EQ(149u, orig_pixels[1][1]);
318  EXPECT_EQ(149u, orig_pixels[1][2]);
319  EXPECT_EQ(0u, orig_pixels[1][3]);
320  EXPECT_EQ(76u, orig_pixels[2][0]);
321  EXPECT_EQ(76u, orig_pixels[2][1]);
322  EXPECT_EQ(76u, orig_pixels[2][2]);
323  EXPECT_EQ(255u, orig_pixels[2][3]);
324  EXPECT_EQ(0u, orig_pixels[3][0]);
325  EXPECT_EQ(0u, orig_pixels[3][1]);
326  EXPECT_EQ(0u, orig_pixels[3][2]);
327  EXPECT_EQ(255u, orig_pixels[3][3]);
328  EXPECT_EQ(255u, orig_pixels[4][0]);
329  EXPECT_EQ(255u, orig_pixels[4][1]);
330  EXPECT_EQ(255u, orig_pixels[4][2]);
331  EXPECT_EQ(255u, orig_pixels[4][3]);
332  EXPECT_EQ(96u, orig_pixels[5][0]);
333  EXPECT_EQ(96u, orig_pixels[5][1]);
334  EXPECT_EQ(96u, orig_pixels[5][2]);
335  EXPECT_EQ(224u, orig_pixels[5][3]);
336  for (int i = 0; i < 1280; ++i) {
337    orig_pixels[i][0] = i;
338    orig_pixels[i][1] = i / 2;
339    orig_pixels[i][2] = i / 3;
340    orig_pixels[i][3] = i;
341  }
342  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
343    ARGBGray(&orig_pixels[0][0], 0, 0, 0, 1280, 1);
344  }
345}
346
347TEST_F(libyuvTest, TestARGBGrayTo) {
348  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
349  SIMD_ALIGNED(uint8 gray_pixels[1280][4]);
350  memset(orig_pixels, 0, sizeof(orig_pixels));
351
352  // Test blue
353  orig_pixels[0][0] = 255u;
354  orig_pixels[0][1] = 0u;
355  orig_pixels[0][2] = 0u;
356  orig_pixels[0][3] = 128u;
357  // Test green
358  orig_pixels[1][0] = 0u;
359  orig_pixels[1][1] = 255u;
360  orig_pixels[1][2] = 0u;
361  orig_pixels[1][3] = 0u;
362  // Test red
363  orig_pixels[2][0] = 0u;
364  orig_pixels[2][1] = 0u;
365  orig_pixels[2][2] = 255u;
366  orig_pixels[2][3] = 255u;
367  // Test black
368  orig_pixels[3][0] = 0u;
369  orig_pixels[3][1] = 0u;
370  orig_pixels[3][2] = 0u;
371  orig_pixels[3][3] = 255u;
372  // Test white
373  orig_pixels[4][0] = 255u;
374  orig_pixels[4][1] = 255u;
375  orig_pixels[4][2] = 255u;
376  orig_pixels[4][3] = 255u;
377  // Test color
378  orig_pixels[5][0] = 16u;
379  orig_pixels[5][1] = 64u;
380  orig_pixels[5][2] = 192u;
381  orig_pixels[5][3] = 224u;
382  // Do 16 to test asm version.
383  ARGBGrayTo(&orig_pixels[0][0], 0, &gray_pixels[0][0], 0, 16, 1);
384  EXPECT_EQ(30u, gray_pixels[0][0]);
385  EXPECT_EQ(30u, gray_pixels[0][1]);
386  EXPECT_EQ(30u, gray_pixels[0][2]);
387  EXPECT_EQ(128u, gray_pixels[0][3]);
388  EXPECT_EQ(149u, gray_pixels[1][0]);
389  EXPECT_EQ(149u, gray_pixels[1][1]);
390  EXPECT_EQ(149u, gray_pixels[1][2]);
391  EXPECT_EQ(0u, gray_pixels[1][3]);
392  EXPECT_EQ(76u, gray_pixels[2][0]);
393  EXPECT_EQ(76u, gray_pixels[2][1]);
394  EXPECT_EQ(76u, gray_pixels[2][2]);
395  EXPECT_EQ(255u, gray_pixels[2][3]);
396  EXPECT_EQ(0u, gray_pixels[3][0]);
397  EXPECT_EQ(0u, gray_pixels[3][1]);
398  EXPECT_EQ(0u, gray_pixels[3][2]);
399  EXPECT_EQ(255u, gray_pixels[3][3]);
400  EXPECT_EQ(255u, gray_pixels[4][0]);
401  EXPECT_EQ(255u, gray_pixels[4][1]);
402  EXPECT_EQ(255u, gray_pixels[4][2]);
403  EXPECT_EQ(255u, gray_pixels[4][3]);
404  EXPECT_EQ(96u, gray_pixels[5][0]);
405  EXPECT_EQ(96u, gray_pixels[5][1]);
406  EXPECT_EQ(96u, gray_pixels[5][2]);
407  EXPECT_EQ(224u, gray_pixels[5][3]);
408  for (int i = 0; i < 1280; ++i) {
409    orig_pixels[i][0] = i;
410    orig_pixels[i][1] = i / 2;
411    orig_pixels[i][2] = i / 3;
412    orig_pixels[i][3] = i;
413  }
414  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
415    ARGBGrayTo(&orig_pixels[0][0], 0, &gray_pixels[0][0], 0, 1280, 1);
416  }
417}
418
419TEST_F(libyuvTest, TestARGBSepia) {
420  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
421  memset(orig_pixels, 0, sizeof(orig_pixels));
422
423  // Test blue
424  orig_pixels[0][0] = 255u;
425  orig_pixels[0][1] = 0u;
426  orig_pixels[0][2] = 0u;
427  orig_pixels[0][3] = 128u;
428  // Test green
429  orig_pixels[1][0] = 0u;
430  orig_pixels[1][1] = 255u;
431  orig_pixels[1][2] = 0u;
432  orig_pixels[1][3] = 0u;
433  // Test red
434  orig_pixels[2][0] = 0u;
435  orig_pixels[2][1] = 0u;
436  orig_pixels[2][2] = 255u;
437  orig_pixels[2][3] = 255u;
438  // Test black
439  orig_pixels[3][0] = 0u;
440  orig_pixels[3][1] = 0u;
441  orig_pixels[3][2] = 0u;
442  orig_pixels[3][3] = 255u;
443  // Test white
444  orig_pixels[4][0] = 255u;
445  orig_pixels[4][1] = 255u;
446  orig_pixels[4][2] = 255u;
447  orig_pixels[4][3] = 255u;
448  // Test color
449  orig_pixels[5][0] = 16u;
450  orig_pixels[5][1] = 64u;
451  orig_pixels[5][2] = 192u;
452  orig_pixels[5][3] = 224u;
453  // Do 16 to test asm version.
454  ARGBSepia(&orig_pixels[0][0], 0, 0, 0, 16, 1);
455  EXPECT_EQ(33u, orig_pixels[0][0]);
456  EXPECT_EQ(43u, orig_pixels[0][1]);
457  EXPECT_EQ(47u, orig_pixels[0][2]);
458  EXPECT_EQ(128u, orig_pixels[0][3]);
459  EXPECT_EQ(135u, orig_pixels[1][0]);
460  EXPECT_EQ(175u, orig_pixels[1][1]);
461  EXPECT_EQ(195u, orig_pixels[1][2]);
462  EXPECT_EQ(0u, orig_pixels[1][3]);
463  EXPECT_EQ(69u, orig_pixels[2][0]);
464  EXPECT_EQ(89u, orig_pixels[2][1]);
465  EXPECT_EQ(99u, orig_pixels[2][2]);
466  EXPECT_EQ(255u, orig_pixels[2][3]);
467  EXPECT_EQ(0u, orig_pixels[3][0]);
468  EXPECT_EQ(0u, orig_pixels[3][1]);
469  EXPECT_EQ(0u, orig_pixels[3][2]);
470  EXPECT_EQ(255u, orig_pixels[3][3]);
471  EXPECT_EQ(239u, orig_pixels[4][0]);
472  EXPECT_EQ(255u, orig_pixels[4][1]);
473  EXPECT_EQ(255u, orig_pixels[4][2]);
474  EXPECT_EQ(255u, orig_pixels[4][3]);
475  EXPECT_EQ(88u, orig_pixels[5][0]);
476  EXPECT_EQ(114u, orig_pixels[5][1]);
477  EXPECT_EQ(127u, orig_pixels[5][2]);
478  EXPECT_EQ(224u, orig_pixels[5][3]);
479
480  for (int i = 0; i < 1280; ++i) {
481    orig_pixels[i][0] = i;
482    orig_pixels[i][1] = i / 2;
483    orig_pixels[i][2] = i / 3;
484    orig_pixels[i][3] = i;
485  }
486  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
487    ARGBSepia(&orig_pixels[0][0], 0, 0, 0, 1280, 1);
488  }
489}
490
491TEST_F(libyuvTest, TestARGBColorMatrix) {
492  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
493  SIMD_ALIGNED(uint8 dst_pixels_opt[1280][4]);
494  SIMD_ALIGNED(uint8 dst_pixels_c[1280][4]);
495
496  // Matrix for Sepia.
497  SIMD_ALIGNED(static const int8 kRGBToSepia[]) = {
498    17 / 2, 68 / 2, 35 / 2, 0,
499    22 / 2, 88 / 2, 45 / 2, 0,
500    24 / 2, 98 / 2, 50 / 2, 0,
501    0, 0, 0, 64,  // Copy alpha.
502  };
503  memset(orig_pixels, 0, sizeof(orig_pixels));
504
505  // Test blue
506  orig_pixels[0][0] = 255u;
507  orig_pixels[0][1] = 0u;
508  orig_pixels[0][2] = 0u;
509  orig_pixels[0][3] = 128u;
510  // Test green
511  orig_pixels[1][0] = 0u;
512  orig_pixels[1][1] = 255u;
513  orig_pixels[1][2] = 0u;
514  orig_pixels[1][3] = 0u;
515  // Test red
516  orig_pixels[2][0] = 0u;
517  orig_pixels[2][1] = 0u;
518  orig_pixels[2][2] = 255u;
519  orig_pixels[2][3] = 255u;
520  // Test color
521  orig_pixels[3][0] = 16u;
522  orig_pixels[3][1] = 64u;
523  orig_pixels[3][2] = 192u;
524  orig_pixels[3][3] = 224u;
525  // Do 16 to test asm version.
526  ARGBColorMatrix(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
527                  &kRGBToSepia[0], 16, 1);
528  EXPECT_EQ(31u, dst_pixels_opt[0][0]);
529  EXPECT_EQ(43u, dst_pixels_opt[0][1]);
530  EXPECT_EQ(47u, dst_pixels_opt[0][2]);
531  EXPECT_EQ(128u, dst_pixels_opt[0][3]);
532  EXPECT_EQ(135u, dst_pixels_opt[1][0]);
533  EXPECT_EQ(175u, dst_pixels_opt[1][1]);
534  EXPECT_EQ(195u, dst_pixels_opt[1][2]);
535  EXPECT_EQ(0u, dst_pixels_opt[1][3]);
536  EXPECT_EQ(67u, dst_pixels_opt[2][0]);
537  EXPECT_EQ(87u, dst_pixels_opt[2][1]);
538  EXPECT_EQ(99u, dst_pixels_opt[2][2]);
539  EXPECT_EQ(255u, dst_pixels_opt[2][3]);
540  EXPECT_EQ(87u, dst_pixels_opt[3][0]);
541  EXPECT_EQ(112u, dst_pixels_opt[3][1]);
542  EXPECT_EQ(127u, dst_pixels_opt[3][2]);
543  EXPECT_EQ(224u, dst_pixels_opt[3][3]);
544
545  for (int i = 0; i < 1280; ++i) {
546    orig_pixels[i][0] = i;
547    orig_pixels[i][1] = i / 2;
548    orig_pixels[i][2] = i / 3;
549    orig_pixels[i][3] = i;
550  }
551  MaskCpuFlags(0);
552  ARGBColorMatrix(&orig_pixels[0][0], 0, &dst_pixels_c[0][0], 0,
553                  &kRGBToSepia[0], 1280, 1);
554  MaskCpuFlags(-1);
555
556  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
557    ARGBColorMatrix(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
558                    &kRGBToSepia[0], 1280, 1);
559  }
560
561  for (int i = 0; i < 1280; ++i) {
562    EXPECT_EQ(dst_pixels_c[i][0], dst_pixels_opt[i][0]);
563    EXPECT_EQ(dst_pixels_c[i][1], dst_pixels_opt[i][1]);
564    EXPECT_EQ(dst_pixels_c[i][2], dst_pixels_opt[i][2]);
565    EXPECT_EQ(dst_pixels_c[i][3], dst_pixels_opt[i][3]);
566  }
567}
568
569TEST_F(libyuvTest, TestRGBColorMatrix) {
570  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
571
572  // Matrix for Sepia.
573  SIMD_ALIGNED(static const int8 kRGBToSepia[]) = {
574    17, 68, 35, 0,
575    22, 88, 45, 0,
576    24, 98, 50, 0,
577    0, 0, 0, 0,  // Unused but makes matrix 16 bytes.
578  };
579  memset(orig_pixels, 0, sizeof(orig_pixels));
580
581  // Test blue
582  orig_pixels[0][0] = 255u;
583  orig_pixels[0][1] = 0u;
584  orig_pixels[0][2] = 0u;
585  orig_pixels[0][3] = 128u;
586  // Test green
587  orig_pixels[1][0] = 0u;
588  orig_pixels[1][1] = 255u;
589  orig_pixels[1][2] = 0u;
590  orig_pixels[1][3] = 0u;
591  // Test red
592  orig_pixels[2][0] = 0u;
593  orig_pixels[2][1] = 0u;
594  orig_pixels[2][2] = 255u;
595  orig_pixels[2][3] = 255u;
596  // Test color
597  orig_pixels[3][0] = 16u;
598  orig_pixels[3][1] = 64u;
599  orig_pixels[3][2] = 192u;
600  orig_pixels[3][3] = 224u;
601  // Do 16 to test asm version.
602  RGBColorMatrix(&orig_pixels[0][0], 0, &kRGBToSepia[0], 0, 0, 16, 1);
603  EXPECT_EQ(31u, orig_pixels[0][0]);
604  EXPECT_EQ(43u, orig_pixels[0][1]);
605  EXPECT_EQ(47u, orig_pixels[0][2]);
606  EXPECT_EQ(128u, orig_pixels[0][3]);
607  EXPECT_EQ(135u, orig_pixels[1][0]);
608  EXPECT_EQ(175u, orig_pixels[1][1]);
609  EXPECT_EQ(195u, orig_pixels[1][2]);
610  EXPECT_EQ(0u, orig_pixels[1][3]);
611  EXPECT_EQ(67u, orig_pixels[2][0]);
612  EXPECT_EQ(87u, orig_pixels[2][1]);
613  EXPECT_EQ(99u, orig_pixels[2][2]);
614  EXPECT_EQ(255u, orig_pixels[2][3]);
615  EXPECT_EQ(87u, orig_pixels[3][0]);
616  EXPECT_EQ(112u, orig_pixels[3][1]);
617  EXPECT_EQ(127u, orig_pixels[3][2]);
618  EXPECT_EQ(224u, orig_pixels[3][3]);
619
620  for (int i = 0; i < 1280; ++i) {
621    orig_pixels[i][0] = i;
622    orig_pixels[i][1] = i / 2;
623    orig_pixels[i][2] = i / 3;
624    orig_pixels[i][3] = i;
625  }
626  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
627    RGBColorMatrix(&orig_pixels[0][0], 0, &kRGBToSepia[0], 0, 0, 1280, 1);
628  }
629}
630
631TEST_F(libyuvTest, TestARGBColorTable) {
632  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
633  memset(orig_pixels, 0, sizeof(orig_pixels));
634
635  // Matrix for Sepia.
636  static const uint8 kARGBTable[256 * 4] = {
637    1u, 2u, 3u, 4u,
638    5u, 6u, 7u, 8u,
639    9u, 10u, 11u, 12u,
640    13u, 14u, 15u, 16u,
641  };
642
643  orig_pixels[0][0] = 0u;
644  orig_pixels[0][1] = 0u;
645  orig_pixels[0][2] = 0u;
646  orig_pixels[0][3] = 0u;
647  orig_pixels[1][0] = 1u;
648  orig_pixels[1][1] = 1u;
649  orig_pixels[1][2] = 1u;
650  orig_pixels[1][3] = 1u;
651  orig_pixels[2][0] = 2u;
652  orig_pixels[2][1] = 2u;
653  orig_pixels[2][2] = 2u;
654  orig_pixels[2][3] = 2u;
655  orig_pixels[3][0] = 0u;
656  orig_pixels[3][1] = 1u;
657  orig_pixels[3][2] = 2u;
658  orig_pixels[3][3] = 3u;
659  // Do 16 to test asm version.
660  ARGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 16, 1);
661  EXPECT_EQ(1u, orig_pixels[0][0]);
662  EXPECT_EQ(2u, orig_pixels[0][1]);
663  EXPECT_EQ(3u, orig_pixels[0][2]);
664  EXPECT_EQ(4u, orig_pixels[0][3]);
665  EXPECT_EQ(5u, orig_pixels[1][0]);
666  EXPECT_EQ(6u, orig_pixels[1][1]);
667  EXPECT_EQ(7u, orig_pixels[1][2]);
668  EXPECT_EQ(8u, orig_pixels[1][3]);
669  EXPECT_EQ(9u, orig_pixels[2][0]);
670  EXPECT_EQ(10u, orig_pixels[2][1]);
671  EXPECT_EQ(11u, orig_pixels[2][2]);
672  EXPECT_EQ(12u, orig_pixels[2][3]);
673  EXPECT_EQ(1u, orig_pixels[3][0]);
674  EXPECT_EQ(6u, orig_pixels[3][1]);
675  EXPECT_EQ(11u, orig_pixels[3][2]);
676  EXPECT_EQ(16u, orig_pixels[3][3]);
677
678  for (int i = 0; i < 1280; ++i) {
679    orig_pixels[i][0] = i;
680    orig_pixels[i][1] = i / 2;
681    orig_pixels[i][2] = i / 3;
682    orig_pixels[i][3] = i;
683  }
684  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
685    ARGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 1280, 1);
686  }
687}
688
689// Same as TestARGBColorTable except alpha does not change.
690TEST_F(libyuvTest, TestRGBColorTable) {
691  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
692  memset(orig_pixels, 0, sizeof(orig_pixels));
693
694  // Matrix for Sepia.
695  static const uint8 kARGBTable[256 * 4] = {
696    1u, 2u, 3u, 4u,
697    5u, 6u, 7u, 8u,
698    9u, 10u, 11u, 12u,
699    13u, 14u, 15u, 16u,
700  };
701
702  orig_pixels[0][0] = 0u;
703  orig_pixels[0][1] = 0u;
704  orig_pixels[0][2] = 0u;
705  orig_pixels[0][3] = 0u;
706  orig_pixels[1][0] = 1u;
707  orig_pixels[1][1] = 1u;
708  orig_pixels[1][2] = 1u;
709  orig_pixels[1][3] = 1u;
710  orig_pixels[2][0] = 2u;
711  orig_pixels[2][1] = 2u;
712  orig_pixels[2][2] = 2u;
713  orig_pixels[2][3] = 2u;
714  orig_pixels[3][0] = 0u;
715  orig_pixels[3][1] = 1u;
716  orig_pixels[3][2] = 2u;
717  orig_pixels[3][3] = 3u;
718  // Do 16 to test asm version.
719  RGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 16, 1);
720  EXPECT_EQ(1u, orig_pixels[0][0]);
721  EXPECT_EQ(2u, orig_pixels[0][1]);
722  EXPECT_EQ(3u, orig_pixels[0][2]);
723  EXPECT_EQ(0u, orig_pixels[0][3]);  // Alpha unchanged.
724  EXPECT_EQ(5u, orig_pixels[1][0]);
725  EXPECT_EQ(6u, orig_pixels[1][1]);
726  EXPECT_EQ(7u, orig_pixels[1][2]);
727  EXPECT_EQ(1u, orig_pixels[1][3]);  // Alpha unchanged.
728  EXPECT_EQ(9u, orig_pixels[2][0]);
729  EXPECT_EQ(10u, orig_pixels[2][1]);
730  EXPECT_EQ(11u, orig_pixels[2][2]);
731  EXPECT_EQ(2u, orig_pixels[2][3]);  // Alpha unchanged.
732  EXPECT_EQ(1u, orig_pixels[3][0]);
733  EXPECT_EQ(6u, orig_pixels[3][1]);
734  EXPECT_EQ(11u, orig_pixels[3][2]);
735  EXPECT_EQ(3u, orig_pixels[3][3]);  // Alpha unchanged.
736
737  for (int i = 0; i < 1280; ++i) {
738    orig_pixels[i][0] = i;
739    orig_pixels[i][1] = i / 2;
740    orig_pixels[i][2] = i / 3;
741    orig_pixels[i][3] = i;
742  }
743  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
744    RGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 1280, 1);
745  }
746}
747
748TEST_F(libyuvTest, TestARGBQuantize) {
749  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
750
751  for (int i = 0; i < 1280; ++i) {
752    orig_pixels[i][0] = i;
753    orig_pixels[i][1] = i / 2;
754    orig_pixels[i][2] = i / 3;
755    orig_pixels[i][3] = i;
756  }
757  ARGBQuantize(&orig_pixels[0][0], 0,
758               (65536 + (8 / 2)) / 8, 8, 8 / 2, 0, 0, 1280, 1);
759
760  for (int i = 0; i < 1280; ++i) {
761    EXPECT_EQ((i / 8 * 8 + 8 / 2) & 255, orig_pixels[i][0]);
762    EXPECT_EQ((i / 2 / 8 * 8 + 8 / 2) & 255, orig_pixels[i][1]);
763    EXPECT_EQ((i / 3 / 8 * 8 + 8 / 2) & 255, orig_pixels[i][2]);
764    EXPECT_EQ(i & 255, orig_pixels[i][3]);
765  }
766  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
767    ARGBQuantize(&orig_pixels[0][0], 0,
768                 (65536 + (8 / 2)) / 8, 8, 8 / 2, 0, 0, 1280, 1);
769  }
770}
771
772TEST_F(libyuvTest, TestARGBMirror) {
773  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
774  SIMD_ALIGNED(uint8 dst_pixels[1280][4]);
775
776  for (int i = 0; i < 1280; ++i) {
777    orig_pixels[i][0] = i;
778    orig_pixels[i][1] = i / 2;
779    orig_pixels[i][2] = i / 3;
780    orig_pixels[i][3] = i / 4;
781  }
782  ARGBMirror(&orig_pixels[0][0], 0, &dst_pixels[0][0], 0, 1280, 1);
783
784  for (int i = 0; i < 1280; ++i) {
785    EXPECT_EQ(i & 255, dst_pixels[1280 - 1 - i][0]);
786    EXPECT_EQ((i / 2) & 255, dst_pixels[1280 - 1 - i][1]);
787    EXPECT_EQ((i / 3) & 255, dst_pixels[1280 - 1 - i][2]);
788    EXPECT_EQ((i / 4) & 255, dst_pixels[1280 - 1 - i][3]);
789  }
790  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
791    ARGBMirror(&orig_pixels[0][0], 0, &dst_pixels[0][0], 0, 1280, 1);
792  }
793}
794
795TEST_F(libyuvTest, TestShade) {
796  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
797  SIMD_ALIGNED(uint8 shade_pixels[1280][4]);
798  memset(orig_pixels, 0, sizeof(orig_pixels));
799
800  orig_pixels[0][0] = 10u;
801  orig_pixels[0][1] = 20u;
802  orig_pixels[0][2] = 40u;
803  orig_pixels[0][3] = 80u;
804  orig_pixels[1][0] = 0u;
805  orig_pixels[1][1] = 0u;
806  orig_pixels[1][2] = 0u;
807  orig_pixels[1][3] = 255u;
808  orig_pixels[2][0] = 0u;
809  orig_pixels[2][1] = 0u;
810  orig_pixels[2][2] = 0u;
811  orig_pixels[2][3] = 0u;
812  orig_pixels[3][0] = 0u;
813  orig_pixels[3][1] = 0u;
814  orig_pixels[3][2] = 0u;
815  orig_pixels[3][3] = 0u;
816  // Do 8 pixels to allow opt version to be used.
817  ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 8, 1, 0x80ffffff);
818  EXPECT_EQ(10u, shade_pixels[0][0]);
819  EXPECT_EQ(20u, shade_pixels[0][1]);
820  EXPECT_EQ(40u, shade_pixels[0][2]);
821  EXPECT_EQ(40u, shade_pixels[0][3]);
822  EXPECT_EQ(0u, shade_pixels[1][0]);
823  EXPECT_EQ(0u, shade_pixels[1][1]);
824  EXPECT_EQ(0u, shade_pixels[1][2]);
825  EXPECT_EQ(128u, shade_pixels[1][3]);
826  EXPECT_EQ(0u, shade_pixels[2][0]);
827  EXPECT_EQ(0u, shade_pixels[2][1]);
828  EXPECT_EQ(0u, shade_pixels[2][2]);
829  EXPECT_EQ(0u, shade_pixels[2][3]);
830  EXPECT_EQ(0u, shade_pixels[3][0]);
831  EXPECT_EQ(0u, shade_pixels[3][1]);
832  EXPECT_EQ(0u, shade_pixels[3][2]);
833  EXPECT_EQ(0u, shade_pixels[3][3]);
834
835  ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 8, 1, 0x80808080);
836  EXPECT_EQ(5u, shade_pixels[0][0]);
837  EXPECT_EQ(10u, shade_pixels[0][1]);
838  EXPECT_EQ(20u, shade_pixels[0][2]);
839  EXPECT_EQ(40u, shade_pixels[0][3]);
840
841  ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 8, 1, 0x10204080);
842  EXPECT_EQ(5u, shade_pixels[0][0]);
843  EXPECT_EQ(5u, shade_pixels[0][1]);
844  EXPECT_EQ(5u, shade_pixels[0][2]);
845  EXPECT_EQ(5u, shade_pixels[0][3]);
846
847  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
848    ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 1280, 1,
849              0x80808080);
850  }
851}
852
853TEST_F(libyuvTest, TestInterpolate) {
854  SIMD_ALIGNED(uint8 orig_pixels_0[1280][4]);
855  SIMD_ALIGNED(uint8 orig_pixels_1[1280][4]);
856  SIMD_ALIGNED(uint8 interpolate_pixels[1280][4]);
857  memset(orig_pixels_0, 0, sizeof(orig_pixels_0));
858  memset(orig_pixels_1, 0, sizeof(orig_pixels_1));
859
860  orig_pixels_0[0][0] = 16u;
861  orig_pixels_0[0][1] = 32u;
862  orig_pixels_0[0][2] = 64u;
863  orig_pixels_0[0][3] = 128u;
864  orig_pixels_0[1][0] = 0u;
865  orig_pixels_0[1][1] = 0u;
866  orig_pixels_0[1][2] = 0u;
867  orig_pixels_0[1][3] = 255u;
868  orig_pixels_0[2][0] = 0u;
869  orig_pixels_0[2][1] = 0u;
870  orig_pixels_0[2][2] = 0u;
871  orig_pixels_0[2][3] = 0u;
872  orig_pixels_0[3][0] = 0u;
873  orig_pixels_0[3][1] = 0u;
874  orig_pixels_0[3][2] = 0u;
875  orig_pixels_0[3][3] = 0u;
876
877  orig_pixels_1[0][0] = 0u;
878  orig_pixels_1[0][1] = 0u;
879  orig_pixels_1[0][2] = 0u;
880  orig_pixels_1[0][3] = 0u;
881  orig_pixels_1[1][0] = 0u;
882  orig_pixels_1[1][1] = 0u;
883  orig_pixels_1[1][2] = 0u;
884  orig_pixels_1[1][3] = 0u;
885  orig_pixels_1[2][0] = 0u;
886  orig_pixels_1[2][1] = 0u;
887  orig_pixels_1[2][2] = 0u;
888  orig_pixels_1[2][3] = 0u;
889  orig_pixels_1[3][0] = 255u;
890  orig_pixels_1[3][1] = 255u;
891  orig_pixels_1[3][2] = 255u;
892  orig_pixels_1[3][3] = 255u;
893
894  ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
895                  &interpolate_pixels[0][0], 0, 4, 1, 128);
896  EXPECT_EQ(8u, interpolate_pixels[0][0]);
897  EXPECT_EQ(16u, interpolate_pixels[0][1]);
898  EXPECT_EQ(32u, interpolate_pixels[0][2]);
899  EXPECT_EQ(64u, interpolate_pixels[0][3]);
900  EXPECT_EQ(0u, interpolate_pixels[1][0]);
901  EXPECT_EQ(0u, interpolate_pixels[1][1]);
902  EXPECT_EQ(0u, interpolate_pixels[1][2]);
903  EXPECT_NEAR(128u, interpolate_pixels[1][3], 1);  // C = 127, SSE = 128.
904  EXPECT_EQ(0u, interpolate_pixels[2][0]);
905  EXPECT_EQ(0u, interpolate_pixels[2][1]);
906  EXPECT_EQ(0u, interpolate_pixels[2][2]);
907  EXPECT_EQ(0u, interpolate_pixels[2][3]);
908  EXPECT_NEAR(128u, interpolate_pixels[3][0], 1);
909  EXPECT_NEAR(128u, interpolate_pixels[3][1], 1);
910  EXPECT_NEAR(128u, interpolate_pixels[3][2], 1);
911  EXPECT_NEAR(128u, interpolate_pixels[3][3], 1);
912
913  ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
914                  &interpolate_pixels[0][0], 0, 4, 1, 0);
915  EXPECT_EQ(16u, interpolate_pixels[0][0]);
916  EXPECT_EQ(32u, interpolate_pixels[0][1]);
917  EXPECT_EQ(64u, interpolate_pixels[0][2]);
918  EXPECT_EQ(128u, interpolate_pixels[0][3]);
919
920  ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
921                  &interpolate_pixels[0][0], 0, 4, 1, 192);
922
923  EXPECT_EQ(4u, interpolate_pixels[0][0]);
924  EXPECT_EQ(8u, interpolate_pixels[0][1]);
925  EXPECT_EQ(16u, interpolate_pixels[0][2]);
926  EXPECT_EQ(32u, interpolate_pixels[0][3]);
927
928  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
929    ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
930                    &interpolate_pixels[0][0], 0, 1280, 1, 128);
931  }
932}
933
934#define TESTTERP(FMT_A, BPP_A, STRIDE_A,                                       \
935                 FMT_B, BPP_B, STRIDE_B,                                       \
936                 W1280, TERP, DIFF, N, NEG, OFF)                               \
937TEST_F(libyuvTest, ARGBInterpolate##TERP##N) {                                 \
938  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
939  const int kHeight = benchmark_height_;                                       \
940  const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
941  const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;  \
942  align_buffer_64(src_argb_a, kStrideA * kHeight + OFF);                       \
943  align_buffer_64(src_argb_b, kStrideA * kHeight + OFF);                       \
944  align_buffer_64(dst_argb_c, kStrideB * kHeight);                             \
945  align_buffer_64(dst_argb_opt, kStrideB * kHeight);                           \
946  srandom(time(NULL));                                                         \
947  for (int i = 0; i < kStrideA * kHeight; ++i) {                               \
948    src_argb_a[i + OFF] = (random() & 0xff);                                   \
949    src_argb_b[i + OFF] = (random() & 0xff);                                   \
950  }                                                                            \
951  MaskCpuFlags(0);                                                             \
952  ARGBInterpolate(src_argb_a + OFF, kStrideA,                                  \
953                  src_argb_b + OFF, kStrideA,                                  \
954                  dst_argb_c, kStrideB,                                        \
955                  kWidth, NEG kHeight, TERP);                                  \
956  MaskCpuFlags(-1);                                                            \
957  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
958    ARGBInterpolate(src_argb_a + OFF, kStrideA,                                \
959                    src_argb_b + OFF, kStrideA,                                \
960                    dst_argb_opt, kStrideB,                                    \
961                    kWidth, NEG kHeight, TERP);                                \
962  }                                                                            \
963  int max_diff = 0;                                                            \
964  for (int i = 0; i < kStrideB * kHeight; ++i) {                               \
965    int abs_diff =                                                             \
966        abs(static_cast<int>(dst_argb_c[i]) -                                  \
967            static_cast<int>(dst_argb_opt[i]));                                \
968    if (abs_diff > max_diff) {                                                 \
969      max_diff = abs_diff;                                                     \
970    }                                                                          \
971  }                                                                            \
972  EXPECT_LE(max_diff, DIFF);                                                   \
973  free_aligned_buffer_64(src_argb_a);                                          \
974  free_aligned_buffer_64(src_argb_b);                                          \
975  free_aligned_buffer_64(dst_argb_c);                                          \
976  free_aligned_buffer_64(dst_argb_opt);                                        \
977}
978
979#define TESTINTERPOLATE(TERP)                                                  \
980    TESTTERP(ARGB, 4, 1, ARGB, 4, 1,                                           \
981             benchmark_width_ - 1, TERP, 1, _Any, +, 0)                        \
982    TESTTERP(ARGB, 4, 1, ARGB, 4, 1,                                           \
983             benchmark_width_, TERP, 1, _Unaligned, +, 1)                      \
984    TESTTERP(ARGB, 4, 1, ARGB, 4, 1,                                           \
985             benchmark_width_, TERP, 1, _Invert, -, 0)                         \
986    TESTTERP(ARGB, 4, 1, ARGB, 4, 1,                                           \
987             benchmark_width_, TERP, 1, _Opt, +, 0)                            \
988    TESTTERP(ARGB, 4, 1, ARGB, 4, 1,                                           \
989             benchmark_width_ - 1, TERP, 1, _Any_Invert, -, 0)
990
991TESTINTERPOLATE(0)
992TESTINTERPOLATE(64)
993TESTINTERPOLATE(128)
994TESTINTERPOLATE(192)
995TESTINTERPOLATE(255)
996
997static int TestBlend(int width, int height, int benchmark_iterations,
998                     int invert, int off) {
999  if (width < 1) {
1000    width = 1;
1001  }
1002  const int kBpp = 4;
1003  const int kStride = width * kBpp;
1004  align_buffer_64(src_argb_a, kStride * height + off);
1005  align_buffer_64(src_argb_b, kStride * height + off);
1006  align_buffer_64(dst_argb_c, kStride * height);
1007  align_buffer_64(dst_argb_opt, kStride * height);
1008  srandom(time(NULL));
1009  for (int i = 0; i < kStride * height; ++i) {
1010    src_argb_a[i + off] = (random() & 0xff);
1011    src_argb_b[i + off] = (random() & 0xff);
1012  }
1013  ARGBAttenuate(src_argb_a + off, kStride, src_argb_a + off, kStride, width,
1014                height);
1015  ARGBAttenuate(src_argb_b + off, kStride, src_argb_b + off, kStride, width,
1016                height);
1017  memset(dst_argb_c, 255, kStride * height);
1018  memset(dst_argb_opt, 255, kStride * height);
1019
1020  MaskCpuFlags(0);
1021  ARGBBlend(src_argb_a + off, kStride,
1022            src_argb_b + off, kStride,
1023            dst_argb_c, kStride,
1024            width, invert * height);
1025  MaskCpuFlags(-1);
1026  for (int i = 0; i < benchmark_iterations; ++i) {
1027    ARGBBlend(src_argb_a + off, kStride,
1028              src_argb_b + off, kStride,
1029              dst_argb_opt, kStride,
1030              width, invert * height);
1031  }
1032  int max_diff = 0;
1033  for (int i = 0; i < kStride * height; ++i) {
1034    int abs_diff =
1035        abs(static_cast<int>(dst_argb_c[i]) -
1036            static_cast<int>(dst_argb_opt[i]));
1037    if (abs_diff > max_diff) {
1038      max_diff = abs_diff;
1039    }
1040  }
1041  free_aligned_buffer_64(src_argb_a);
1042  free_aligned_buffer_64(src_argb_b);
1043  free_aligned_buffer_64(dst_argb_c);
1044  free_aligned_buffer_64(dst_argb_opt);
1045  return max_diff;
1046}
1047
1048TEST_F(libyuvTest, ARGBBlend_Any) {
1049  int max_diff = TestBlend(benchmark_width_ - 4, benchmark_height_,
1050                           benchmark_iterations_, +1, 0);
1051  EXPECT_LE(max_diff, 1);
1052}
1053
1054TEST_F(libyuvTest, ARGBBlend_Unaligned) {
1055  int max_diff = TestBlend(benchmark_width_, benchmark_height_,
1056                           benchmark_iterations_, +1, 1);
1057  EXPECT_LE(max_diff, 1);
1058}
1059
1060TEST_F(libyuvTest, ARGBBlend_Invert) {
1061  int max_diff = TestBlend(benchmark_width_, benchmark_height_,
1062                           benchmark_iterations_, -1, 0);
1063  EXPECT_LE(max_diff, 1);
1064}
1065
1066TEST_F(libyuvTest, ARGBBlend_Opt) {
1067  int max_diff = TestBlend(benchmark_width_, benchmark_height_,
1068                           benchmark_iterations_, +1, 0);
1069  EXPECT_LE(max_diff, 1);
1070}
1071
1072TEST_F(libyuvTest, TestAffine) {
1073  SIMD_ALIGNED(uint8 orig_pixels_0[1280][4]);
1074  SIMD_ALIGNED(uint8 interpolate_pixels_C[1280][4]);
1075
1076  for (int i = 0; i < 1280; ++i) {
1077    for (int j = 0; j < 4; ++j) {
1078      orig_pixels_0[i][j] = i;
1079    }
1080  }
1081
1082  float uv_step[4] = { 0.f, 0.f, 0.75f, 0.f };
1083
1084  ARGBAffineRow_C(&orig_pixels_0[0][0], 0, &interpolate_pixels_C[0][0],
1085                  uv_step, 1280);
1086  EXPECT_EQ(0u, interpolate_pixels_C[0][0]);
1087  EXPECT_EQ(96u, interpolate_pixels_C[128][0]);
1088  EXPECT_EQ(191u, interpolate_pixels_C[255][3]);
1089
1090#if defined(HAS_ARGBAFFINEROW_SSE2)
1091  SIMD_ALIGNED(uint8 interpolate_pixels_Opt[1280][4]);
1092  ARGBAffineRow_SSE2(&orig_pixels_0[0][0], 0, &interpolate_pixels_Opt[0][0],
1093                     uv_step, 1280);
1094  EXPECT_EQ(0, memcmp(interpolate_pixels_Opt, interpolate_pixels_C, 1280 * 4));
1095
1096  int has_sse2 = TestCpuFlag(kCpuHasSSE2);
1097  if (has_sse2) {
1098    for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1099      ARGBAffineRow_SSE2(&orig_pixels_0[0][0], 0, &interpolate_pixels_Opt[0][0],
1100                         uv_step, 1280);
1101    }
1102  }
1103#endif
1104}
1105
1106TEST_F(libyuvTest, TestSobelX) {
1107  SIMD_ALIGNED(uint8 orig_pixels_0[1280 + 2]);
1108  SIMD_ALIGNED(uint8 orig_pixels_1[1280 + 2]);
1109  SIMD_ALIGNED(uint8 orig_pixels_2[1280 + 2]);
1110  SIMD_ALIGNED(uint8 sobel_pixels_c[1280]);
1111  SIMD_ALIGNED(uint8 sobel_pixels_opt[1280]);
1112
1113  for (int i = 0; i < 1280 + 2; ++i) {
1114    orig_pixels_0[i] = i;
1115    orig_pixels_1[i] = i * 2;
1116    orig_pixels_2[i] = i * 3;
1117  }
1118
1119  SobelXRow_C(orig_pixels_0, orig_pixels_1, orig_pixels_2,
1120              sobel_pixels_c, 1280);
1121
1122  EXPECT_EQ(16u, sobel_pixels_c[0]);
1123  EXPECT_EQ(16u, sobel_pixels_c[100]);
1124  EXPECT_EQ(255u, sobel_pixels_c[255]);
1125
1126  void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1,
1127                    const uint8* src_y2, uint8* dst_sobely, int width) =
1128      SobelXRow_C;
1129#if defined(HAS_SOBELXROW_SSE2)
1130  if (TestCpuFlag(kCpuHasSSE2)) {
1131    SobelXRow = SobelXRow_SSE2;
1132  }
1133#endif
1134#if defined(HAS_SOBELXROW_NEON)
1135  if (TestCpuFlag(kCpuHasNEON)) {
1136    SobelXRow = SobelXRow_NEON;
1137  }
1138#endif
1139  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1140    SobelXRow(orig_pixels_0, orig_pixels_1, orig_pixels_2,
1141              sobel_pixels_opt, 1280);
1142  }
1143  for (int i = 0; i < 1280; ++i) {
1144    EXPECT_EQ(sobel_pixels_c[i], sobel_pixels_opt[i]);
1145  }
1146}
1147
1148TEST_F(libyuvTest, TestSobelY) {
1149  SIMD_ALIGNED(uint8 orig_pixels_0[1280 + 2]);
1150  SIMD_ALIGNED(uint8 orig_pixels_1[1280 + 2]);
1151  SIMD_ALIGNED(uint8 sobel_pixels_c[1280]);
1152  SIMD_ALIGNED(uint8 sobel_pixels_opt[1280]);
1153
1154  for (int i = 0; i < 1280 + 2; ++i) {
1155    orig_pixels_0[i] = i;
1156    orig_pixels_1[i] = i * 2;
1157  }
1158
1159  SobelYRow_C(orig_pixels_0, orig_pixels_1, sobel_pixels_c, 1280);
1160
1161  EXPECT_EQ(4u, sobel_pixels_c[0]);
1162  EXPECT_EQ(255u, sobel_pixels_c[100]);
1163  EXPECT_EQ(0u, sobel_pixels_c[255]);
1164  void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1,
1165                    uint8* dst_sobely, int width) = SobelYRow_C;
1166#if defined(HAS_SOBELYROW_SSE2)
1167  if (TestCpuFlag(kCpuHasSSE2)) {
1168    SobelYRow = SobelYRow_SSE2;
1169  }
1170#endif
1171#if defined(HAS_SOBELYROW_NEON)
1172  if (TestCpuFlag(kCpuHasNEON)) {
1173    SobelYRow = SobelYRow_NEON;
1174  }
1175#endif
1176  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1177    SobelYRow(orig_pixels_0, orig_pixels_1, sobel_pixels_opt, 1280);
1178  }
1179  for (int i = 0; i < 1280; ++i) {
1180    EXPECT_EQ(sobel_pixels_c[i], sobel_pixels_opt[i]);
1181  }
1182}
1183
1184TEST_F(libyuvTest, TestSobel) {
1185  SIMD_ALIGNED(uint8 orig_sobelx[1280]);
1186  SIMD_ALIGNED(uint8 orig_sobely[1280]);
1187  SIMD_ALIGNED(uint8 sobel_pixels_c[1280 * 4]);
1188  SIMD_ALIGNED(uint8 sobel_pixels_opt[1280 * 4]);
1189
1190  for (int i = 0; i < 1280; ++i) {
1191    orig_sobelx[i] = i;
1192    orig_sobely[i] = i * 2;
1193  }
1194
1195  SobelRow_C(orig_sobelx, orig_sobely, sobel_pixels_c, 1280);
1196
1197  EXPECT_EQ(0u, sobel_pixels_c[0]);
1198  EXPECT_EQ(3u, sobel_pixels_c[4]);
1199  EXPECT_EQ(3u, sobel_pixels_c[5]);
1200  EXPECT_EQ(3u, sobel_pixels_c[6]);
1201  EXPECT_EQ(255u, sobel_pixels_c[7]);
1202  EXPECT_EQ(6u, sobel_pixels_c[8]);
1203  EXPECT_EQ(6u, sobel_pixels_c[9]);
1204  EXPECT_EQ(6u, sobel_pixels_c[10]);
1205  EXPECT_EQ(255u, sobel_pixels_c[7]);
1206  EXPECT_EQ(255u, sobel_pixels_c[100 * 4 + 1]);
1207  EXPECT_EQ(255u, sobel_pixels_c[255 * 4 + 1]);
1208  void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely,
1209                   uint8* dst_argb, int width) = SobelRow_C;
1210#if defined(HAS_SOBELROW_SSE2)
1211  if (TestCpuFlag(kCpuHasSSE2)) {
1212    SobelRow = SobelRow_SSE2;
1213  }
1214#endif
1215#if defined(HAS_SOBELROW_NEON)
1216  if (TestCpuFlag(kCpuHasNEON)) {
1217    SobelRow = SobelRow_NEON;
1218  }
1219#endif
1220  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1221    SobelRow(orig_sobelx, orig_sobely, sobel_pixels_opt, 1280);
1222  }
1223  for (int i = 0; i < 1280 * 4; ++i) {
1224    EXPECT_EQ(sobel_pixels_c[i], sobel_pixels_opt[i]);
1225  }
1226}
1227
1228TEST_F(libyuvTest, TestSobelToPlane) {
1229  SIMD_ALIGNED(uint8 orig_sobelx[1280]);
1230  SIMD_ALIGNED(uint8 orig_sobely[1280]);
1231  SIMD_ALIGNED(uint8 sobel_pixels_c[1280]);
1232  SIMD_ALIGNED(uint8 sobel_pixels_opt[1280]);
1233
1234  for (int i = 0; i < 1280; ++i) {
1235    orig_sobelx[i] = i;
1236    orig_sobely[i] = i * 2;
1237  }
1238
1239  SobelToPlaneRow_C(orig_sobelx, orig_sobely, sobel_pixels_c, 1280);
1240
1241  EXPECT_EQ(0u, sobel_pixels_c[0]);
1242  EXPECT_EQ(3u, sobel_pixels_c[1]);
1243  EXPECT_EQ(6u, sobel_pixels_c[2]);
1244  EXPECT_EQ(99u, sobel_pixels_c[33]);
1245  EXPECT_EQ(255u, sobel_pixels_c[100]);
1246  void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely,
1247                          uint8* dst_y, int width) = SobelToPlaneRow_C;
1248#if defined(HAS_SOBELTOPLANEROW_SSE2)
1249  if (TestCpuFlag(kCpuHasSSE2)) {
1250    SobelToPlaneRow = SobelToPlaneRow_SSE2;
1251  }
1252#endif
1253#if defined(HAS_SOBELTOPLANEROW_NEON)
1254  if (TestCpuFlag(kCpuHasNEON)) {
1255    SobelToPlaneRow = SobelToPlaneRow_NEON;
1256  }
1257#endif
1258  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1259    SobelToPlaneRow(orig_sobelx, orig_sobely, sobel_pixels_opt, 1280);
1260  }
1261  for (int i = 0; i < 1280; ++i) {
1262    EXPECT_EQ(sobel_pixels_c[i], sobel_pixels_opt[i]);
1263  }
1264}
1265
1266TEST_F(libyuvTest, TestSobelXY) {
1267  SIMD_ALIGNED(uint8 orig_sobelx[1280]);
1268  SIMD_ALIGNED(uint8 orig_sobely[1280]);
1269  SIMD_ALIGNED(uint8 sobel_pixels_c[1280 * 4]);
1270  SIMD_ALIGNED(uint8 sobel_pixels_opt[1280 * 4]);
1271
1272  for (int i = 0; i < 1280; ++i) {
1273    orig_sobelx[i] = i;
1274    orig_sobely[i] = i * 2;
1275  }
1276
1277  SobelXYRow_C(orig_sobelx, orig_sobely, sobel_pixels_c, 1280);
1278
1279  EXPECT_EQ(0u, sobel_pixels_c[0]);
1280  EXPECT_EQ(2u, sobel_pixels_c[4]);
1281  EXPECT_EQ(3u, sobel_pixels_c[5]);
1282  EXPECT_EQ(1u, sobel_pixels_c[6]);
1283  EXPECT_EQ(255u, sobel_pixels_c[7]);
1284  EXPECT_EQ(255u, sobel_pixels_c[100 * 4 + 1]);
1285  EXPECT_EQ(255u, sobel_pixels_c[255 * 4 + 1]);
1286  void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely,
1287                       uint8* dst_argb, int width) = SobelXYRow_C;
1288#if defined(HAS_SOBELXYROW_SSE2)
1289  if (TestCpuFlag(kCpuHasSSE2)) {
1290    SobelXYRow = SobelXYRow_SSE2;
1291  }
1292#endif
1293#if defined(HAS_SOBELXYROW_NEON)
1294  if (TestCpuFlag(kCpuHasNEON)) {
1295    SobelXYRow = SobelXYRow_NEON;
1296  }
1297#endif
1298  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1299    SobelXYRow(orig_sobelx, orig_sobely, sobel_pixels_opt, 1280);
1300  }
1301  for (int i = 0; i < 1280 * 4; ++i) {
1302    EXPECT_EQ(sobel_pixels_c[i], sobel_pixels_opt[i]);
1303  }
1304}
1305
1306TEST_F(libyuvTest, TestCopyPlane) {
1307  int err = 0;
1308  int yw = benchmark_width_;
1309  int yh = benchmark_height_;
1310  int b = 12;
1311  int i, j;
1312
1313  int y_plane_size = (yw + b * 2) * (yh + b * 2);
1314  srandom(time(NULL));
1315  align_buffer_64(orig_y, y_plane_size);
1316  align_buffer_64(dst_c, y_plane_size);
1317  align_buffer_64(dst_opt, y_plane_size);
1318
1319  memset(orig_y, 0, y_plane_size);
1320  memset(dst_c, 0, y_plane_size);
1321  memset(dst_opt, 0, y_plane_size);
1322
1323  // Fill image buffers with random data.
1324  for (i = b; i < (yh + b); ++i) {
1325    for (j = b; j < (yw + b); ++j) {
1326      orig_y[i * (yw + b * 2) + j] = random() & 0xff;
1327    }
1328  }
1329
1330  // Fill destination buffers with random data.
1331  for (i = 0; i < y_plane_size; ++i) {
1332    uint8 random_number = random() & 0x7f;
1333    dst_c[i] = random_number;
1334    dst_opt[i] = dst_c[i];
1335  }
1336
1337  int y_off = b * (yw + b * 2) + b;
1338
1339  int y_st = yw + b * 2;
1340  int stride = 8;
1341
1342  // Disable all optimizations.
1343  MaskCpuFlags(0);
1344  double c_time = get_time();
1345  for (j = 0; j < benchmark_iterations_; j++) {
1346    CopyPlane(orig_y + y_off, y_st, dst_c + y_off, stride, yw, yh);
1347  }
1348  c_time = (get_time() - c_time) / benchmark_iterations_;
1349
1350  // Enable optimizations.
1351  MaskCpuFlags(-1);
1352  double opt_time = get_time();
1353  for (j = 0; j < benchmark_iterations_; j++) {
1354    CopyPlane(orig_y + y_off, y_st, dst_opt + y_off, stride, yw, yh);
1355  }
1356  opt_time = (get_time() - opt_time) / benchmark_iterations_;
1357
1358  for (i = 0; i < y_plane_size; ++i) {
1359    if (dst_c[i] != dst_opt[i])
1360      ++err;
1361  }
1362
1363  free_aligned_buffer_64(orig_y);
1364  free_aligned_buffer_64(dst_c);
1365  free_aligned_buffer_64(dst_opt);
1366
1367  EXPECT_EQ(0, err);
1368}
1369
1370static int TestMultiply(int width, int height, int benchmark_iterations,
1371                        int invert, int off) {
1372  if (width < 1) {
1373    width = 1;
1374  }
1375  const int kBpp = 4;
1376  const int kStride = (width * kBpp + 15) & ~15;
1377  align_buffer_64(src_argb_a, kStride * height + off);
1378  align_buffer_64(src_argb_b, kStride * height + off);
1379  align_buffer_64(dst_argb_c, kStride * height);
1380  align_buffer_64(dst_argb_opt, kStride * height);
1381  srandom(time(NULL));
1382  for (int i = 0; i < kStride * height; ++i) {
1383    src_argb_a[i + off] = (random() & 0xff);
1384    src_argb_b[i + off] = (random() & 0xff);
1385  }
1386  memset(dst_argb_c, 0, kStride * height);
1387  memset(dst_argb_opt, 0, kStride * height);
1388
1389  MaskCpuFlags(0);
1390  ARGBMultiply(src_argb_a + off, kStride,
1391               src_argb_b + off, kStride,
1392               dst_argb_c, kStride,
1393               width, invert * height);
1394  MaskCpuFlags(-1);
1395  for (int i = 0; i < benchmark_iterations; ++i) {
1396    ARGBMultiply(src_argb_a + off, kStride,
1397                 src_argb_b + off, kStride,
1398                 dst_argb_opt, kStride,
1399                 width, invert * height);
1400  }
1401  int max_diff = 0;
1402  for (int i = 0; i < kStride * height; ++i) {
1403    int abs_diff =
1404        abs(static_cast<int>(dst_argb_c[i]) -
1405            static_cast<int>(dst_argb_opt[i]));
1406    if (abs_diff > max_diff) {
1407      max_diff = abs_diff;
1408    }
1409  }
1410  free_aligned_buffer_64(src_argb_a);
1411  free_aligned_buffer_64(src_argb_b);
1412  free_aligned_buffer_64(dst_argb_c);
1413  free_aligned_buffer_64(dst_argb_opt);
1414  return max_diff;
1415}
1416
1417TEST_F(libyuvTest, ARGBMultiply_Any) {
1418  int max_diff = TestMultiply(benchmark_width_ - 1, benchmark_height_,
1419                              benchmark_iterations_, +1, 0);
1420  EXPECT_LE(max_diff, 1);
1421}
1422
1423TEST_F(libyuvTest, ARGBMultiply_Unaligned) {
1424  int max_diff = TestMultiply(benchmark_width_, benchmark_height_,
1425                              benchmark_iterations_, +1, 1);
1426  EXPECT_LE(max_diff, 1);
1427}
1428
1429TEST_F(libyuvTest, ARGBMultiply_Invert) {
1430  int max_diff = TestMultiply(benchmark_width_, benchmark_height_,
1431                              benchmark_iterations_, -1, 0);
1432  EXPECT_LE(max_diff, 1);
1433}
1434
1435TEST_F(libyuvTest, ARGBMultiply_Opt) {
1436  int max_diff = TestMultiply(benchmark_width_, benchmark_height_,
1437                              benchmark_iterations_, +1, 0);
1438  EXPECT_LE(max_diff, 1);
1439}
1440
1441static int TestAdd(int width, int height, int benchmark_iterations,
1442                   int invert, int off) {
1443  if (width < 1) {
1444    width = 1;
1445  }
1446  const int kBpp = 4;
1447  const int kStride = (width * kBpp + 15) & ~15;
1448  align_buffer_64(src_argb_a, kStride * height + off);
1449  align_buffer_64(src_argb_b, kStride * height + off);
1450  align_buffer_64(dst_argb_c, kStride * height);
1451  align_buffer_64(dst_argb_opt, kStride * height);
1452  srandom(time(NULL));
1453  for (int i = 0; i < kStride * height; ++i) {
1454    src_argb_a[i + off] = (random() & 0xff);
1455    src_argb_b[i + off] = (random() & 0xff);
1456  }
1457  memset(dst_argb_c, 0, kStride * height);
1458  memset(dst_argb_opt, 0, kStride * height);
1459
1460  MaskCpuFlags(0);
1461  ARGBAdd(src_argb_a + off, kStride,
1462          src_argb_b + off, kStride,
1463          dst_argb_c, kStride,
1464          width, invert * height);
1465  MaskCpuFlags(-1);
1466  for (int i = 0; i < benchmark_iterations; ++i) {
1467    ARGBAdd(src_argb_a + off, kStride,
1468            src_argb_b + off, kStride,
1469            dst_argb_opt, kStride,
1470            width, invert * height);
1471  }
1472  int max_diff = 0;
1473  for (int i = 0; i < kStride * height; ++i) {
1474    int abs_diff =
1475        abs(static_cast<int>(dst_argb_c[i]) -
1476            static_cast<int>(dst_argb_opt[i]));
1477    if (abs_diff > max_diff) {
1478      max_diff = abs_diff;
1479    }
1480  }
1481  free_aligned_buffer_64(src_argb_a);
1482  free_aligned_buffer_64(src_argb_b);
1483  free_aligned_buffer_64(dst_argb_c);
1484  free_aligned_buffer_64(dst_argb_opt);
1485  return max_diff;
1486}
1487
1488TEST_F(libyuvTest, ARGBAdd_Any) {
1489  int max_diff = TestAdd(benchmark_width_ - 1, benchmark_height_,
1490                         benchmark_iterations_, +1, 0);
1491  EXPECT_LE(max_diff, 1);
1492}
1493
1494TEST_F(libyuvTest, ARGBAdd_Unaligned) {
1495  int max_diff = TestAdd(benchmark_width_, benchmark_height_,
1496                         benchmark_iterations_, +1, 1);
1497  EXPECT_LE(max_diff, 1);
1498}
1499
1500TEST_F(libyuvTest, ARGBAdd_Invert) {
1501  int max_diff = TestAdd(benchmark_width_, benchmark_height_,
1502                         benchmark_iterations_, -1, 0);
1503  EXPECT_LE(max_diff, 1);
1504}
1505
1506TEST_F(libyuvTest, ARGBAdd_Opt) {
1507  int max_diff = TestAdd(benchmark_width_, benchmark_height_,
1508                         benchmark_iterations_, +1, 0);
1509  EXPECT_LE(max_diff, 1);
1510}
1511
1512static int TestSubtract(int width, int height, int benchmark_iterations,
1513                        int invert, int off) {
1514  if (width < 1) {
1515    width = 1;
1516  }
1517  const int kBpp = 4;
1518  const int kStride = (width * kBpp + 15) & ~15;
1519  align_buffer_64(src_argb_a, kStride * height + off);
1520  align_buffer_64(src_argb_b, kStride * height + off);
1521  align_buffer_64(dst_argb_c, kStride * height);
1522  align_buffer_64(dst_argb_opt, kStride * height);
1523  srandom(time(NULL));
1524  for (int i = 0; i < kStride * height; ++i) {
1525    src_argb_a[i + off] = (random() & 0xff);
1526    src_argb_b[i + off] = (random() & 0xff);
1527  }
1528  memset(dst_argb_c, 0, kStride * height);
1529  memset(dst_argb_opt, 0, kStride * height);
1530
1531  MaskCpuFlags(0);
1532  ARGBSubtract(src_argb_a + off, kStride,
1533               src_argb_b + off, kStride,
1534               dst_argb_c, kStride,
1535               width, invert * height);
1536  MaskCpuFlags(-1);
1537  for (int i = 0; i < benchmark_iterations; ++i) {
1538    ARGBSubtract(src_argb_a + off, kStride,
1539                 src_argb_b + off, kStride,
1540                 dst_argb_opt, kStride,
1541                 width, invert * height);
1542  }
1543  int max_diff = 0;
1544  for (int i = 0; i < kStride * height; ++i) {
1545    int abs_diff =
1546        abs(static_cast<int>(dst_argb_c[i]) -
1547            static_cast<int>(dst_argb_opt[i]));
1548    if (abs_diff > max_diff) {
1549      max_diff = abs_diff;
1550    }
1551  }
1552  free_aligned_buffer_64(src_argb_a);
1553  free_aligned_buffer_64(src_argb_b);
1554  free_aligned_buffer_64(dst_argb_c);
1555  free_aligned_buffer_64(dst_argb_opt);
1556  return max_diff;
1557}
1558
1559TEST_F(libyuvTest, ARGBSubtract_Any) {
1560  int max_diff = TestSubtract(benchmark_width_ - 1, benchmark_height_,
1561                              benchmark_iterations_, +1, 0);
1562  EXPECT_LE(max_diff, 1);
1563}
1564
1565TEST_F(libyuvTest, ARGBSubtract_Unaligned) {
1566  int max_diff = TestSubtract(benchmark_width_, benchmark_height_,
1567                              benchmark_iterations_, +1, 1);
1568  EXPECT_LE(max_diff, 1);
1569}
1570
1571TEST_F(libyuvTest, ARGBSubtract_Invert) {
1572  int max_diff = TestSubtract(benchmark_width_, benchmark_height_,
1573                              benchmark_iterations_, -1, 0);
1574  EXPECT_LE(max_diff, 1);
1575}
1576
1577TEST_F(libyuvTest, ARGBSubtract_Opt) {
1578  int max_diff = TestSubtract(benchmark_width_, benchmark_height_,
1579                              benchmark_iterations_, +1, 0);
1580  EXPECT_LE(max_diff, 1);
1581}
1582
1583static int TestSobel(int width, int height, int benchmark_iterations,
1584                     int invert, int off) {
1585  if (width < 1) {
1586    width = 1;
1587  }
1588  const int kBpp = 4;
1589  const int kStride = (width * kBpp + 15) & ~15;
1590  align_buffer_64(src_argb_a, kStride * height + off);
1591  align_buffer_64(dst_argb_c, kStride * height);
1592  align_buffer_64(dst_argb_opt, kStride * height);
1593  memset(src_argb_a, 0, kStride * height + off);
1594  srandom(time(NULL));
1595  for (int i = 0; i < kStride * height; ++i) {
1596    src_argb_a[i + off] = (random() & 0xff);
1597  }
1598  memset(dst_argb_c, 0, kStride * height);
1599  memset(dst_argb_opt, 0, kStride * height);
1600
1601  MaskCpuFlags(0);
1602  ARGBSobel(src_argb_a + off, kStride,
1603            dst_argb_c, kStride,
1604            width, invert * height);
1605  MaskCpuFlags(-1);
1606  for (int i = 0; i < benchmark_iterations; ++i) {
1607    ARGBSobel(src_argb_a + off, kStride,
1608              dst_argb_opt, kStride,
1609              width, invert * height);
1610  }
1611  int max_diff = 0;
1612  for (int i = 0; i < kStride * height; ++i) {
1613    int abs_diff =
1614        abs(static_cast<int>(dst_argb_c[i]) -
1615            static_cast<int>(dst_argb_opt[i]));
1616    if (abs_diff > max_diff) {
1617      max_diff = abs_diff;
1618    }
1619  }
1620  free_aligned_buffer_64(src_argb_a);
1621  free_aligned_buffer_64(dst_argb_c);
1622  free_aligned_buffer_64(dst_argb_opt);
1623  return max_diff;
1624}
1625
1626TEST_F(libyuvTest, ARGBSobel_Any) {
1627  int max_diff = TestSobel(benchmark_width_ - 1, benchmark_height_,
1628                           benchmark_iterations_, +1, 0);
1629  EXPECT_EQ(0, max_diff);
1630}
1631
1632TEST_F(libyuvTest, ARGBSobel_Unaligned) {
1633  int max_diff = TestSobel(benchmark_width_, benchmark_height_,
1634                           benchmark_iterations_, +1, 1);
1635  EXPECT_EQ(0, max_diff);
1636}
1637
1638TEST_F(libyuvTest, ARGBSobel_Invert) {
1639  int max_diff = TestSobel(benchmark_width_, benchmark_height_,
1640                           benchmark_iterations_, -1, 0);
1641  EXPECT_EQ(0, max_diff);
1642}
1643
1644TEST_F(libyuvTest, ARGBSobel_Opt) {
1645  int max_diff = TestSobel(benchmark_width_, benchmark_height_,
1646                           benchmark_iterations_, +1, 0);
1647  EXPECT_EQ(0, max_diff);
1648}
1649
1650static int TestSobelToPlane(int width, int height, int benchmark_iterations,
1651                            int invert, int off) {
1652  if (width < 1) {
1653    width = 1;
1654  }
1655  const int kSrcBpp = 4;
1656  const int kDstBpp = 1;
1657  const int kSrcStride = (width * kSrcBpp + 15) & ~15;
1658  const int kDstStride = (width * kDstBpp + 15) & ~15;
1659  align_buffer_64(src_argb_a, kSrcStride * height + off);
1660  align_buffer_64(dst_argb_c, kDstStride * height);
1661  align_buffer_64(dst_argb_opt, kDstStride * height);
1662  memset(src_argb_a, 0, kSrcStride * height + off);
1663  srandom(time(NULL));
1664  for (int i = 0; i < kSrcStride * height; ++i) {
1665    src_argb_a[i + off] = (random() & 0xff);
1666  }
1667  memset(dst_argb_c, 0, kDstStride * height);
1668  memset(dst_argb_opt, 0, kDstStride * height);
1669
1670  MaskCpuFlags(0);
1671  ARGBSobelToPlane(src_argb_a + off, kSrcStride,
1672                   dst_argb_c, kDstStride,
1673                   width, invert * height);
1674  MaskCpuFlags(-1);
1675  for (int i = 0; i < benchmark_iterations; ++i) {
1676    ARGBSobelToPlane(src_argb_a + off, kSrcStride,
1677                     dst_argb_opt, kDstStride,
1678                     width, invert * height);
1679  }
1680  int max_diff = 0;
1681  for (int i = 0; i < kDstStride * height; ++i) {
1682    int abs_diff =
1683        abs(static_cast<int>(dst_argb_c[i]) -
1684            static_cast<int>(dst_argb_opt[i]));
1685    if (abs_diff > max_diff) {
1686      max_diff = abs_diff;
1687    }
1688  }
1689  free_aligned_buffer_64(src_argb_a);
1690  free_aligned_buffer_64(dst_argb_c);
1691  free_aligned_buffer_64(dst_argb_opt);
1692  return max_diff;
1693}
1694
1695TEST_F(libyuvTest, ARGBSobelToPlane_Any) {
1696  int max_diff = TestSobelToPlane(benchmark_width_ - 1, benchmark_height_,
1697                                  benchmark_iterations_, +1, 0);
1698  EXPECT_EQ(0, max_diff);
1699}
1700
1701TEST_F(libyuvTest, ARGBSobelToPlane_Unaligned) {
1702  int max_diff = TestSobelToPlane(benchmark_width_, benchmark_height_,
1703                                  benchmark_iterations_, +1, 1);
1704  EXPECT_EQ(0, max_diff);
1705}
1706
1707TEST_F(libyuvTest, ARGBSobelToPlane_Invert) {
1708  int max_diff = TestSobelToPlane(benchmark_width_, benchmark_height_,
1709                                  benchmark_iterations_, -1, 0);
1710  EXPECT_EQ(0, max_diff);
1711}
1712
1713TEST_F(libyuvTest, ARGBSobelToPlane_Opt) {
1714  int max_diff = TestSobelToPlane(benchmark_width_, benchmark_height_,
1715                                  benchmark_iterations_, +1, 0);
1716  EXPECT_EQ(0, max_diff);
1717}
1718
1719static int TestSobelXY(int width, int height, int benchmark_iterations,
1720                     int invert, int off) {
1721  if (width < 1) {
1722    width = 1;
1723  }
1724  const int kBpp = 4;
1725  const int kStride = (width * kBpp + 15) & ~15;
1726  align_buffer_64(src_argb_a, kStride * height + off);
1727  align_buffer_64(dst_argb_c, kStride * height);
1728  align_buffer_64(dst_argb_opt, kStride * height);
1729  memset(src_argb_a, 0, kStride * height + off);
1730  srandom(time(NULL));
1731  for (int i = 0; i < kStride * height; ++i) {
1732    src_argb_a[i + off] = (random() & 0xff);
1733  }
1734  memset(dst_argb_c, 0, kStride * height);
1735  memset(dst_argb_opt, 0, kStride * height);
1736
1737  MaskCpuFlags(0);
1738  ARGBSobelXY(src_argb_a + off, kStride,
1739            dst_argb_c, kStride,
1740            width, invert * height);
1741  MaskCpuFlags(-1);
1742  for (int i = 0; i < benchmark_iterations; ++i) {
1743    ARGBSobelXY(src_argb_a + off, kStride,
1744              dst_argb_opt, kStride,
1745              width, invert * height);
1746  }
1747  int max_diff = 0;
1748  for (int i = 0; i < kStride * height; ++i) {
1749    int abs_diff =
1750        abs(static_cast<int>(dst_argb_c[i]) -
1751            static_cast<int>(dst_argb_opt[i]));
1752    if (abs_diff > max_diff) {
1753      max_diff = abs_diff;
1754    }
1755  }
1756  free_aligned_buffer_64(src_argb_a);
1757  free_aligned_buffer_64(dst_argb_c);
1758  free_aligned_buffer_64(dst_argb_opt);
1759  return max_diff;
1760}
1761
1762TEST_F(libyuvTest, ARGBSobelXY_Any) {
1763  int max_diff = TestSobelXY(benchmark_width_ - 1, benchmark_height_,
1764                             benchmark_iterations_, +1, 0);
1765  EXPECT_EQ(0, max_diff);
1766}
1767
1768TEST_F(libyuvTest, ARGBSobelXY_Unaligned) {
1769  int max_diff = TestSobelXY(benchmark_width_, benchmark_height_,
1770                             benchmark_iterations_, +1, 1);
1771  EXPECT_EQ(0, max_diff);
1772}
1773
1774TEST_F(libyuvTest, ARGBSobelXY_Invert) {
1775  int max_diff = TestSobelXY(benchmark_width_, benchmark_height_,
1776                             benchmark_iterations_, -1, 0);
1777  EXPECT_EQ(0, max_diff);
1778}
1779
1780TEST_F(libyuvTest, ARGBSobelXY_Opt) {
1781  int max_diff = TestSobelXY(benchmark_width_, benchmark_height_,
1782                             benchmark_iterations_, +1, 0);
1783  EXPECT_EQ(0, max_diff);
1784}
1785
1786static int TestBlur(int width, int height, int benchmark_iterations,
1787                    int invert, int off, int radius) {
1788  if (width < 1) {
1789    width = 1;
1790  }
1791  const int kBpp = 4;
1792  const int kStride = (width * kBpp + 15) & ~15;
1793  align_buffer_64(src_argb_a, kStride * height + off);
1794  align_buffer_64(dst_cumsum, width * height * 16);
1795  align_buffer_64(dst_argb_c, kStride * height);
1796  align_buffer_64(dst_argb_opt, kStride * height);
1797  srandom(time(NULL));
1798  for (int i = 0; i < kStride * height; ++i) {
1799    src_argb_a[i + off] = (random() & 0xff);
1800  }
1801  memset(dst_cumsum, 0, width * height * 16);
1802  memset(dst_argb_c, 0, kStride * height);
1803  memset(dst_argb_opt, 0, kStride * height);
1804
1805  MaskCpuFlags(0);
1806  ARGBBlur(src_argb_a + off, kStride,
1807           dst_argb_c, kStride,
1808           reinterpret_cast<int32*>(dst_cumsum), width * 4,
1809           width, invert * height, radius);
1810  MaskCpuFlags(-1);
1811  for (int i = 0; i < benchmark_iterations; ++i) {
1812    ARGBBlur(src_argb_a + off, kStride,
1813             dst_argb_opt, kStride,
1814             reinterpret_cast<int32*>(dst_cumsum), width * 4,
1815             width, invert * height, radius);
1816  }
1817  int max_diff = 0;
1818  for (int i = 0; i < kStride * height; ++i) {
1819    int abs_diff =
1820        abs(static_cast<int>(dst_argb_c[i]) -
1821            static_cast<int>(dst_argb_opt[i]));
1822    if (abs_diff > max_diff) {
1823      max_diff = abs_diff;
1824    }
1825  }
1826  free_aligned_buffer_64(src_argb_a);
1827  free_aligned_buffer_64(dst_cumsum);
1828  free_aligned_buffer_64(dst_argb_c);
1829  free_aligned_buffer_64(dst_argb_opt);
1830  return max_diff;
1831}
1832
1833static const int kBlurSize = 55;
1834TEST_F(libyuvTest, ARGBBlur_Any) {
1835  int max_diff = TestBlur(benchmark_width_ - 1, benchmark_height_,
1836                          benchmark_iterations_, +1, 0, kBlurSize);
1837  EXPECT_LE(max_diff, 1);
1838}
1839
1840TEST_F(libyuvTest, ARGBBlur_Unaligned) {
1841  int max_diff = TestBlur(benchmark_width_, benchmark_height_,
1842                          benchmark_iterations_, +1, 1, kBlurSize);
1843  EXPECT_LE(max_diff, 1);
1844}
1845
1846TEST_F(libyuvTest, ARGBBlur_Invert) {
1847  int max_diff = TestBlur(benchmark_width_, benchmark_height_,
1848                          benchmark_iterations_, -1, 0, kBlurSize);
1849  EXPECT_LE(max_diff, 1);
1850}
1851
1852TEST_F(libyuvTest, ARGBBlur_Opt) {
1853  int max_diff = TestBlur(benchmark_width_, benchmark_height_,
1854                          benchmark_iterations_, +1, 0, kBlurSize);
1855  EXPECT_LE(max_diff, 1);
1856}
1857
1858static const int kBlurSmallSize = 5;
1859TEST_F(libyuvTest, ARGBBlurSmall_Any) {
1860  int max_diff = TestBlur(benchmark_width_ - 1, benchmark_height_,
1861                          benchmark_iterations_, +1, 0, kBlurSmallSize);
1862  EXPECT_LE(max_diff, 1);
1863}
1864
1865TEST_F(libyuvTest, ARGBBlurSmall_Unaligned) {
1866  int max_diff = TestBlur(benchmark_width_, benchmark_height_,
1867                          benchmark_iterations_, +1, 1, kBlurSmallSize);
1868  EXPECT_LE(max_diff, 1);
1869}
1870
1871TEST_F(libyuvTest, ARGBBlurSmall_Invert) {
1872  int max_diff = TestBlur(benchmark_width_, benchmark_height_,
1873                          benchmark_iterations_, -1, 0, kBlurSmallSize);
1874  EXPECT_LE(max_diff, 1);
1875}
1876
1877TEST_F(libyuvTest, ARGBBlurSmall_Opt) {
1878  int max_diff = TestBlur(benchmark_width_, benchmark_height_,
1879                          benchmark_iterations_, +1, 0, kBlurSmallSize);
1880  EXPECT_LE(max_diff, 1);
1881}
1882
1883TEST_F(libyuvTest, TestARGBPolynomial) {
1884  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
1885  SIMD_ALIGNED(uint8 dst_pixels_opt[1280][4]);
1886  SIMD_ALIGNED(uint8 dst_pixels_c[1280][4]);
1887  memset(orig_pixels, 0, sizeof(orig_pixels));
1888
1889  SIMD_ALIGNED(static const float kWarmifyPolynomial[16]) = {
1890    0.94230f,  -3.03300f,    -2.92500f,  0.f,  // C0
1891    0.584500f,  1.112000f,    1.535000f, 1.f,  // C1 x
1892    0.001313f, -0.002503f,   -0.004496f, 0.f,  // C2 x * x
1893    0.0f,       0.000006965f, 0.000008781f, 0.f,  // C3 x * x * x
1894  };
1895
1896  // Test blue
1897  orig_pixels[0][0] = 255u;
1898  orig_pixels[0][1] = 0u;
1899  orig_pixels[0][2] = 0u;
1900  orig_pixels[0][3] = 128u;
1901  // Test green
1902  orig_pixels[1][0] = 0u;
1903  orig_pixels[1][1] = 255u;
1904  orig_pixels[1][2] = 0u;
1905  orig_pixels[1][3] = 0u;
1906  // Test red
1907  orig_pixels[2][0] = 0u;
1908  orig_pixels[2][1] = 0u;
1909  orig_pixels[2][2] = 255u;
1910  orig_pixels[2][3] = 255u;
1911  // Test white
1912  orig_pixels[3][0] = 255u;
1913  orig_pixels[3][1] = 255u;
1914  orig_pixels[3][2] = 255u;
1915  orig_pixels[3][3] = 255u;
1916  // Test color
1917  orig_pixels[4][0] = 16u;
1918  orig_pixels[4][1] = 64u;
1919  orig_pixels[4][2] = 192u;
1920  orig_pixels[4][3] = 224u;
1921  // Do 16 to test asm version.
1922  ARGBPolynomial(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
1923                 &kWarmifyPolynomial[0], 16, 1);
1924  EXPECT_EQ(235u, dst_pixels_opt[0][0]);
1925  EXPECT_EQ(0u, dst_pixels_opt[0][1]);
1926  EXPECT_EQ(0u, dst_pixels_opt[0][2]);
1927  EXPECT_EQ(128u, dst_pixels_opt[0][3]);
1928  EXPECT_EQ(0u, dst_pixels_opt[1][0]);
1929  EXPECT_EQ(233u, dst_pixels_opt[1][1]);
1930  EXPECT_EQ(0u, dst_pixels_opt[1][2]);
1931  EXPECT_EQ(0u, dst_pixels_opt[1][3]);
1932  EXPECT_EQ(0u, dst_pixels_opt[2][0]);
1933  EXPECT_EQ(0u, dst_pixels_opt[2][1]);
1934  EXPECT_EQ(241u, dst_pixels_opt[2][2]);
1935  EXPECT_EQ(255u, dst_pixels_opt[2][3]);
1936  EXPECT_EQ(235u, dst_pixels_opt[3][0]);
1937  EXPECT_EQ(233u, dst_pixels_opt[3][1]);
1938  EXPECT_EQ(241u, dst_pixels_opt[3][2]);
1939  EXPECT_EQ(255u, dst_pixels_opt[3][3]);
1940  EXPECT_EQ(10u, dst_pixels_opt[4][0]);
1941  EXPECT_EQ(59u, dst_pixels_opt[4][1]);
1942  EXPECT_EQ(188u, dst_pixels_opt[4][2]);
1943  EXPECT_EQ(224u, dst_pixels_opt[4][3]);
1944
1945  for (int i = 0; i < 1280; ++i) {
1946    orig_pixels[i][0] = i;
1947    orig_pixels[i][1] = i / 2;
1948    orig_pixels[i][2] = i / 3;
1949    orig_pixels[i][3] = i;
1950  }
1951
1952  MaskCpuFlags(0);
1953  ARGBPolynomial(&orig_pixels[0][0], 0, &dst_pixels_c[0][0], 0,
1954                 &kWarmifyPolynomial[0], 1280, 1);
1955  MaskCpuFlags(-1);
1956
1957  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1958    ARGBPolynomial(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
1959                   &kWarmifyPolynomial[0], 1280, 1);
1960  }
1961
1962  for (int i = 0; i < 1280; ++i) {
1963    EXPECT_EQ(dst_pixels_c[i][0], dst_pixels_opt[i][0]);
1964    EXPECT_EQ(dst_pixels_c[i][1], dst_pixels_opt[i][1]);
1965    EXPECT_EQ(dst_pixels_c[i][2], dst_pixels_opt[i][2]);
1966    EXPECT_EQ(dst_pixels_c[i][3], dst_pixels_opt[i][3]);
1967  }
1968}
1969
1970TEST_F(libyuvTest, TestARGBLumaColorTable) {
1971  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
1972  SIMD_ALIGNED(uint8 dst_pixels_opt[1280][4]);
1973  SIMD_ALIGNED(uint8 dst_pixels_c[1280][4]);
1974  memset(orig_pixels, 0, sizeof(orig_pixels));
1975
1976  align_buffer_64(lumacolortable, 32768);
1977  int v = 0;
1978  for (int i = 0; i < 32768; ++i) {
1979    lumacolortable[i] = v;
1980    v += 3;
1981  }
1982  // Test blue
1983  orig_pixels[0][0] = 255u;
1984  orig_pixels[0][1] = 0u;
1985  orig_pixels[0][2] = 0u;
1986  orig_pixels[0][3] = 128u;
1987  // Test green
1988  orig_pixels[1][0] = 0u;
1989  orig_pixels[1][1] = 255u;
1990  orig_pixels[1][2] = 0u;
1991  orig_pixels[1][3] = 0u;
1992  // Test red
1993  orig_pixels[2][0] = 0u;
1994  orig_pixels[2][1] = 0u;
1995  orig_pixels[2][2] = 255u;
1996  orig_pixels[2][3] = 255u;
1997  // Test color
1998  orig_pixels[3][0] = 16u;
1999  orig_pixels[3][1] = 64u;
2000  orig_pixels[3][2] = 192u;
2001  orig_pixels[3][3] = 224u;
2002  // Do 16 to test asm version.
2003  ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
2004                     &lumacolortable[0], 16, 1);
2005  EXPECT_EQ(253u, dst_pixels_opt[0][0]);
2006  EXPECT_EQ(0u, dst_pixels_opt[0][1]);
2007  EXPECT_EQ(0u, dst_pixels_opt[0][2]);
2008  EXPECT_EQ(128u, dst_pixels_opt[0][3]);
2009  EXPECT_EQ(0u, dst_pixels_opt[1][0]);
2010  EXPECT_EQ(253u, dst_pixels_opt[1][1]);
2011  EXPECT_EQ(0u, dst_pixels_opt[1][2]);
2012  EXPECT_EQ(0u, dst_pixels_opt[1][3]);
2013  EXPECT_EQ(0u, dst_pixels_opt[2][0]);
2014  EXPECT_EQ(0u, dst_pixels_opt[2][1]);
2015  EXPECT_EQ(253u, dst_pixels_opt[2][2]);
2016  EXPECT_EQ(255u, dst_pixels_opt[2][3]);
2017  EXPECT_EQ(48u, dst_pixels_opt[3][0]);
2018  EXPECT_EQ(192u, dst_pixels_opt[3][1]);
2019  EXPECT_EQ(64u, dst_pixels_opt[3][2]);
2020  EXPECT_EQ(224u, dst_pixels_opt[3][3]);
2021
2022  for (int i = 0; i < 1280; ++i) {
2023    orig_pixels[i][0] = i;
2024    orig_pixels[i][1] = i / 2;
2025    orig_pixels[i][2] = i / 3;
2026    orig_pixels[i][3] = i;
2027  }
2028
2029  MaskCpuFlags(0);
2030  ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels_c[0][0], 0,
2031                     lumacolortable, 1280, 1);
2032  MaskCpuFlags(-1);
2033
2034  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
2035    ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
2036                       lumacolortable, 1280, 1);
2037  }
2038  for (int i = 0; i < 1280; ++i) {
2039    EXPECT_EQ(dst_pixels_c[i][0], dst_pixels_opt[i][0]);
2040    EXPECT_EQ(dst_pixels_c[i][1], dst_pixels_opt[i][1]);
2041    EXPECT_EQ(dst_pixels_c[i][2], dst_pixels_opt[i][2]);
2042    EXPECT_EQ(dst_pixels_c[i][3], dst_pixels_opt[i][3]);
2043  }
2044
2045  free_aligned_buffer_64(lumacolortable);
2046}
2047
2048TEST_F(libyuvTest, TestARGBCopyAlpha) {
2049  const int kSize = benchmark_width_ * benchmark_height_ * 4;
2050  align_buffer_64(orig_pixels, kSize);
2051  align_buffer_64(dst_pixels_opt, kSize);
2052  align_buffer_64(dst_pixels_c, kSize);
2053
2054  MemRandomize(orig_pixels, kSize);
2055  MemRandomize(dst_pixels_opt, kSize);
2056  memcpy(dst_pixels_c, dst_pixels_opt, kSize);
2057
2058  MaskCpuFlags(0);
2059  ARGBCopyAlpha(orig_pixels, benchmark_width_ * 4,
2060                dst_pixels_c, benchmark_width_ * 4,
2061                benchmark_width_, benchmark_height_);
2062  MaskCpuFlags(-1);
2063
2064  for (int i = 0; i < benchmark_iterations_; ++i) {
2065    ARGBCopyAlpha(orig_pixels, benchmark_width_ * 4,
2066                  dst_pixels_opt, benchmark_width_ * 4,
2067                  benchmark_width_, benchmark_height_);
2068  }
2069  for (int i = 0; i < kSize; ++i) {
2070    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2071  }
2072
2073  free_aligned_buffer_64(dst_pixels_c);
2074  free_aligned_buffer_64(dst_pixels_opt);
2075  free_aligned_buffer_64(orig_pixels);
2076}
2077
2078TEST_F(libyuvTest, TestARGBCopyYToAlpha) {
2079  const int kPixels = benchmark_width_ * benchmark_height_;
2080  align_buffer_64(orig_pixels, kPixels);
2081  align_buffer_64(dst_pixels_opt, kPixels * 4);
2082  align_buffer_64(dst_pixels_c, kPixels * 4);
2083
2084  MemRandomize(orig_pixels, kPixels);
2085  MemRandomize(dst_pixels_opt, kPixels * 4);
2086  memcpy(dst_pixels_c, dst_pixels_opt, kPixels * 4);
2087
2088  MaskCpuFlags(0);
2089  ARGBCopyYToAlpha(orig_pixels, benchmark_width_,
2090                   dst_pixels_c, benchmark_width_ * 4,
2091                   benchmark_width_, benchmark_height_);
2092  MaskCpuFlags(-1);
2093
2094  for (int i = 0; i < benchmark_iterations_; ++i) {
2095    ARGBCopyYToAlpha(orig_pixels, benchmark_width_,
2096                     dst_pixels_opt, benchmark_width_ * 4,
2097                     benchmark_width_, benchmark_height_);
2098  }
2099  for (int i = 0; i < kPixels * 4; ++i) {
2100    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2101  }
2102
2103  free_aligned_buffer_64(dst_pixels_c);
2104  free_aligned_buffer_64(dst_pixels_opt);
2105  free_aligned_buffer_64(orig_pixels);
2106}
2107
2108}  // namespace libyuv
2109