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 "../unit_test/unit_test.h"
15#include "libyuv/compare.h"
16#include "libyuv/convert.h"
17#include "libyuv/convert_argb.h"
18#include "libyuv/convert_from.h"
19#include "libyuv/convert_from_argb.h"
20#include "libyuv/cpu_id.h"
21#include "libyuv/planar_functions.h"
22#include "libyuv/rotate.h"
23
24namespace libyuv {
25
26TEST_F(LibYUVPlanarTest, TestAttenuate) {
27  const int kSize = 1280 * 4;
28  align_buffer_page_end(orig_pixels, kSize);
29  align_buffer_page_end(atten_pixels, kSize);
30  align_buffer_page_end(unatten_pixels, kSize);
31  align_buffer_page_end(atten2_pixels, kSize);
32
33  // Test unattenuation clamps
34  orig_pixels[0 * 4 + 0] = 200u;
35  orig_pixels[0 * 4 + 1] = 129u;
36  orig_pixels[0 * 4 + 2] = 127u;
37  orig_pixels[0 * 4 + 3] = 128u;
38  // Test unattenuation transparent and opaque are unaffected
39  orig_pixels[1 * 4 + 0] = 16u;
40  orig_pixels[1 * 4 + 1] = 64u;
41  orig_pixels[1 * 4 + 2] = 192u;
42  orig_pixels[1 * 4 + 3] = 0u;
43  orig_pixels[2 * 4 + 0] = 16u;
44  orig_pixels[2 * 4 + 1] = 64u;
45  orig_pixels[2 * 4 + 2] = 192u;
46  orig_pixels[2 * 4 + 3] = 255u;
47  orig_pixels[3 * 4 + 0] = 16u;
48  orig_pixels[3 * 4 + 1] = 64u;
49  orig_pixels[3 * 4 + 2] = 192u;
50  orig_pixels[3 * 4 + 3] = 128u;
51  ARGBUnattenuate(orig_pixels, 0, unatten_pixels, 0, 4, 1);
52  EXPECT_EQ(255u, unatten_pixels[0 * 4 + 0]);
53  EXPECT_EQ(255u, unatten_pixels[0 * 4 + 1]);
54  EXPECT_EQ(254u, unatten_pixels[0 * 4 + 2]);
55  EXPECT_EQ(128u, unatten_pixels[0 * 4 + 3]);
56  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 0]);
57  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 1]);
58  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 2]);
59  EXPECT_EQ(0u, unatten_pixels[1 * 4 + 3]);
60  EXPECT_EQ(16u, unatten_pixels[2 * 4 + 0]);
61  EXPECT_EQ(64u, unatten_pixels[2 * 4 + 1]);
62  EXPECT_EQ(192u, unatten_pixels[2 * 4 + 2]);
63  EXPECT_EQ(255u, unatten_pixels[2 * 4 + 3]);
64  EXPECT_EQ(32u, unatten_pixels[3 * 4 + 0]);
65  EXPECT_EQ(128u, unatten_pixels[3 * 4 + 1]);
66  EXPECT_EQ(255u, unatten_pixels[3 * 4 + 2]);
67  EXPECT_EQ(128u, unatten_pixels[3 * 4 + 3]);
68
69  for (int i = 0; i < 1280; ++i) {
70    orig_pixels[i * 4 + 0] = i;
71    orig_pixels[i * 4 + 1] = i / 2;
72    orig_pixels[i * 4 + 2] = i / 3;
73    orig_pixels[i * 4 + 3] = i;
74  }
75  ARGBAttenuate(orig_pixels, 0, atten_pixels, 0, 1280, 1);
76  ARGBUnattenuate(atten_pixels, 0, unatten_pixels, 0, 1280, 1);
77  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
78    ARGBAttenuate(unatten_pixels, 0, atten2_pixels, 0, 1280, 1);
79  }
80  for (int i = 0; i < 1280; ++i) {
81    EXPECT_NEAR(atten_pixels[i * 4 + 0], atten2_pixels[i * 4 + 0], 2);
82    EXPECT_NEAR(atten_pixels[i * 4 + 1], atten2_pixels[i * 4 + 1], 2);
83    EXPECT_NEAR(atten_pixels[i * 4 + 2], atten2_pixels[i * 4 + 2], 2);
84    EXPECT_NEAR(atten_pixels[i * 4 + 3], atten2_pixels[i * 4 + 3], 2);
85  }
86  // Make sure transparent, 50% and opaque are fully accurate.
87  EXPECT_EQ(0, atten_pixels[0 * 4 + 0]);
88  EXPECT_EQ(0, atten_pixels[0 * 4 + 1]);
89  EXPECT_EQ(0, atten_pixels[0 * 4 + 2]);
90  EXPECT_EQ(0, atten_pixels[0 * 4 + 3]);
91  EXPECT_EQ(64, atten_pixels[128 * 4 + 0]);
92  EXPECT_EQ(32, atten_pixels[128 * 4 + 1]);
93  EXPECT_EQ(21, atten_pixels[128 * 4 + 2]);
94  EXPECT_EQ(128, atten_pixels[128 * 4 + 3]);
95  EXPECT_NEAR(255, atten_pixels[255 * 4 + 0], 1);
96  EXPECT_NEAR(127, atten_pixels[255 * 4 + 1], 1);
97  EXPECT_NEAR(85, atten_pixels[255 * 4 + 2], 1);
98  EXPECT_EQ(255, atten_pixels[255 * 4 + 3]);
99
100  free_aligned_buffer_page_end(atten2_pixels);
101  free_aligned_buffer_page_end(unatten_pixels);
102  free_aligned_buffer_page_end(atten_pixels);
103  free_aligned_buffer_page_end(orig_pixels);
104}
105
106static int TestAttenuateI(int width,
107                          int height,
108                          int benchmark_iterations,
109                          int disable_cpu_flags,
110                          int benchmark_cpu_info,
111                          int invert,
112                          int off) {
113  if (width < 1) {
114    width = 1;
115  }
116  const int kBpp = 4;
117  const int kStride = width * kBpp;
118  align_buffer_page_end(src_argb, kStride * height + off);
119  align_buffer_page_end(dst_argb_c, kStride * height);
120  align_buffer_page_end(dst_argb_opt, kStride * height);
121  for (int i = 0; i < kStride * height; ++i) {
122    src_argb[i + off] = (fastrand() & 0xff);
123  }
124  memset(dst_argb_c, 0, kStride * height);
125  memset(dst_argb_opt, 0, kStride * height);
126
127  MaskCpuFlags(disable_cpu_flags);
128  ARGBAttenuate(src_argb + off, kStride, dst_argb_c, kStride, width,
129                invert * height);
130  MaskCpuFlags(benchmark_cpu_info);
131  for (int i = 0; i < benchmark_iterations; ++i) {
132    ARGBAttenuate(src_argb + off, kStride, dst_argb_opt, kStride, width,
133                  invert * height);
134  }
135  int max_diff = 0;
136  for (int i = 0; i < kStride * height; ++i) {
137    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
138                       static_cast<int>(dst_argb_opt[i]));
139    if (abs_diff > max_diff) {
140      max_diff = abs_diff;
141    }
142  }
143  free_aligned_buffer_page_end(src_argb);
144  free_aligned_buffer_page_end(dst_argb_c);
145  free_aligned_buffer_page_end(dst_argb_opt);
146  return max_diff;
147}
148
149TEST_F(LibYUVPlanarTest, ARGBAttenuate_Any) {
150  int max_diff = TestAttenuateI(benchmark_width_ - 1, benchmark_height_,
151                                benchmark_iterations_, disable_cpu_flags_,
152                                benchmark_cpu_info_, +1, 0);
153  EXPECT_LE(max_diff, 2);
154}
155
156TEST_F(LibYUVPlanarTest, ARGBAttenuate_Unaligned) {
157  int max_diff =
158      TestAttenuateI(benchmark_width_, benchmark_height_, benchmark_iterations_,
159                     disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
160  EXPECT_LE(max_diff, 2);
161}
162
163TEST_F(LibYUVPlanarTest, ARGBAttenuate_Invert) {
164  int max_diff =
165      TestAttenuateI(benchmark_width_, benchmark_height_, benchmark_iterations_,
166                     disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
167  EXPECT_LE(max_diff, 2);
168}
169
170TEST_F(LibYUVPlanarTest, ARGBAttenuate_Opt) {
171  int max_diff =
172      TestAttenuateI(benchmark_width_, benchmark_height_, benchmark_iterations_,
173                     disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
174  EXPECT_LE(max_diff, 2);
175}
176
177static int TestUnattenuateI(int width,
178                            int height,
179                            int benchmark_iterations,
180                            int disable_cpu_flags,
181                            int benchmark_cpu_info,
182                            int invert,
183                            int off) {
184  if (width < 1) {
185    width = 1;
186  }
187  const int kBpp = 4;
188  const int kStride = width * kBpp;
189  align_buffer_page_end(src_argb, kStride * height + off);
190  align_buffer_page_end(dst_argb_c, kStride * height);
191  align_buffer_page_end(dst_argb_opt, kStride * height);
192  for (int i = 0; i < kStride * height; ++i) {
193    src_argb[i + off] = (fastrand() & 0xff);
194  }
195  ARGBAttenuate(src_argb + off, kStride, src_argb + off, kStride, width,
196                height);
197  memset(dst_argb_c, 0, kStride * height);
198  memset(dst_argb_opt, 0, kStride * height);
199
200  MaskCpuFlags(disable_cpu_flags);
201  ARGBUnattenuate(src_argb + off, kStride, dst_argb_c, kStride, width,
202                  invert * height);
203  MaskCpuFlags(benchmark_cpu_info);
204  for (int i = 0; i < benchmark_iterations; ++i) {
205    ARGBUnattenuate(src_argb + off, kStride, dst_argb_opt, kStride, width,
206                    invert * height);
207  }
208  int max_diff = 0;
209  for (int i = 0; i < kStride * height; ++i) {
210    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
211                       static_cast<int>(dst_argb_opt[i]));
212    if (abs_diff > max_diff) {
213      max_diff = abs_diff;
214    }
215  }
216  free_aligned_buffer_page_end(src_argb);
217  free_aligned_buffer_page_end(dst_argb_c);
218  free_aligned_buffer_page_end(dst_argb_opt);
219  return max_diff;
220}
221
222TEST_F(LibYUVPlanarTest, ARGBUnattenuate_Any) {
223  int max_diff = TestUnattenuateI(benchmark_width_ - 1, benchmark_height_,
224                                  benchmark_iterations_, disable_cpu_flags_,
225                                  benchmark_cpu_info_, +1, 0);
226  EXPECT_LE(max_diff, 2);
227}
228
229TEST_F(LibYUVPlanarTest, ARGBUnattenuate_Unaligned) {
230  int max_diff = TestUnattenuateI(benchmark_width_, benchmark_height_,
231                                  benchmark_iterations_, disable_cpu_flags_,
232                                  benchmark_cpu_info_, +1, 1);
233  EXPECT_LE(max_diff, 2);
234}
235
236TEST_F(LibYUVPlanarTest, ARGBUnattenuate_Invert) {
237  int max_diff = TestUnattenuateI(benchmark_width_, benchmark_height_,
238                                  benchmark_iterations_, disable_cpu_flags_,
239                                  benchmark_cpu_info_, -1, 0);
240  EXPECT_LE(max_diff, 2);
241}
242
243TEST_F(LibYUVPlanarTest, ARGBUnattenuate_Opt) {
244  int max_diff = TestUnattenuateI(benchmark_width_, benchmark_height_,
245                                  benchmark_iterations_, disable_cpu_flags_,
246                                  benchmark_cpu_info_, +1, 0);
247  EXPECT_LE(max_diff, 2);
248}
249
250TEST_F(LibYUVPlanarTest, TestARGBComputeCumulativeSum) {
251  SIMD_ALIGNED(uint8 orig_pixels[16][16][4]);
252  SIMD_ALIGNED(int32 added_pixels[16][16][4]);
253
254  for (int y = 0; y < 16; ++y) {
255    for (int x = 0; x < 16; ++x) {
256      orig_pixels[y][x][0] = 1u;
257      orig_pixels[y][x][1] = 2u;
258      orig_pixels[y][x][2] = 3u;
259      orig_pixels[y][x][3] = 255u;
260    }
261  }
262
263  ARGBComputeCumulativeSum(&orig_pixels[0][0][0], 16 * 4,
264                           &added_pixels[0][0][0], 16 * 4, 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(LibYUVPlanarTest, 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(LibYUVPlanarTest, 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(LibYUVPlanarTest, 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(LibYUVPlanarTest, 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, 22 / 2, 88 / 2, 45 / 2, 0,
499      24 / 2, 98 / 2, 50 / 2, 0, 0,      0,      0,      64,  // Copy alpha.
500  };
501  memset(orig_pixels, 0, sizeof(orig_pixels));
502
503  // Test blue
504  orig_pixels[0][0] = 255u;
505  orig_pixels[0][1] = 0u;
506  orig_pixels[0][2] = 0u;
507  orig_pixels[0][3] = 128u;
508  // Test green
509  orig_pixels[1][0] = 0u;
510  orig_pixels[1][1] = 255u;
511  orig_pixels[1][2] = 0u;
512  orig_pixels[1][3] = 0u;
513  // Test red
514  orig_pixels[2][0] = 0u;
515  orig_pixels[2][1] = 0u;
516  orig_pixels[2][2] = 255u;
517  orig_pixels[2][3] = 255u;
518  // Test color
519  orig_pixels[3][0] = 16u;
520  orig_pixels[3][1] = 64u;
521  orig_pixels[3][2] = 192u;
522  orig_pixels[3][3] = 224u;
523  // Do 16 to test asm version.
524  ARGBColorMatrix(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
525                  &kRGBToSepia[0], 16, 1);
526  EXPECT_EQ(31u, dst_pixels_opt[0][0]);
527  EXPECT_EQ(43u, dst_pixels_opt[0][1]);
528  EXPECT_EQ(47u, dst_pixels_opt[0][2]);
529  EXPECT_EQ(128u, dst_pixels_opt[0][3]);
530  EXPECT_EQ(135u, dst_pixels_opt[1][0]);
531  EXPECT_EQ(175u, dst_pixels_opt[1][1]);
532  EXPECT_EQ(195u, dst_pixels_opt[1][2]);
533  EXPECT_EQ(0u, dst_pixels_opt[1][3]);
534  EXPECT_EQ(67u, dst_pixels_opt[2][0]);
535  EXPECT_EQ(87u, dst_pixels_opt[2][1]);
536  EXPECT_EQ(99u, dst_pixels_opt[2][2]);
537  EXPECT_EQ(255u, dst_pixels_opt[2][3]);
538  EXPECT_EQ(87u, dst_pixels_opt[3][0]);
539  EXPECT_EQ(112u, dst_pixels_opt[3][1]);
540  EXPECT_EQ(127u, dst_pixels_opt[3][2]);
541  EXPECT_EQ(224u, dst_pixels_opt[3][3]);
542
543  for (int i = 0; i < 1280; ++i) {
544    orig_pixels[i][0] = i;
545    orig_pixels[i][1] = i / 2;
546    orig_pixels[i][2] = i / 3;
547    orig_pixels[i][3] = i;
548  }
549  MaskCpuFlags(disable_cpu_flags_);
550  ARGBColorMatrix(&orig_pixels[0][0], 0, &dst_pixels_c[0][0], 0,
551                  &kRGBToSepia[0], 1280, 1);
552  MaskCpuFlags(benchmark_cpu_info_);
553
554  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
555    ARGBColorMatrix(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
556                    &kRGBToSepia[0], 1280, 1);
557  }
558
559  for (int i = 0; i < 1280; ++i) {
560    EXPECT_EQ(dst_pixels_c[i][0], dst_pixels_opt[i][0]);
561    EXPECT_EQ(dst_pixels_c[i][1], dst_pixels_opt[i][1]);
562    EXPECT_EQ(dst_pixels_c[i][2], dst_pixels_opt[i][2]);
563    EXPECT_EQ(dst_pixels_c[i][3], dst_pixels_opt[i][3]);
564  }
565}
566
567TEST_F(LibYUVPlanarTest, TestRGBColorMatrix) {
568  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
569
570  // Matrix for Sepia.
571  SIMD_ALIGNED(static const int8 kRGBToSepia[]) = {
572      17, 68, 35, 0, 22, 88, 45, 0,
573      24, 98, 50, 0, 0,  0,  0,  0,  // Unused but makes matrix 16 bytes.
574  };
575  memset(orig_pixels, 0, sizeof(orig_pixels));
576
577  // Test blue
578  orig_pixels[0][0] = 255u;
579  orig_pixels[0][1] = 0u;
580  orig_pixels[0][2] = 0u;
581  orig_pixels[0][3] = 128u;
582  // Test green
583  orig_pixels[1][0] = 0u;
584  orig_pixels[1][1] = 255u;
585  orig_pixels[1][2] = 0u;
586  orig_pixels[1][3] = 0u;
587  // Test red
588  orig_pixels[2][0] = 0u;
589  orig_pixels[2][1] = 0u;
590  orig_pixels[2][2] = 255u;
591  orig_pixels[2][3] = 255u;
592  // Test color
593  orig_pixels[3][0] = 16u;
594  orig_pixels[3][1] = 64u;
595  orig_pixels[3][2] = 192u;
596  orig_pixels[3][3] = 224u;
597  // Do 16 to test asm version.
598  RGBColorMatrix(&orig_pixels[0][0], 0, &kRGBToSepia[0], 0, 0, 16, 1);
599  EXPECT_EQ(31u, orig_pixels[0][0]);
600  EXPECT_EQ(43u, orig_pixels[0][1]);
601  EXPECT_EQ(47u, orig_pixels[0][2]);
602  EXPECT_EQ(128u, orig_pixels[0][3]);
603  EXPECT_EQ(135u, orig_pixels[1][0]);
604  EXPECT_EQ(175u, orig_pixels[1][1]);
605  EXPECT_EQ(195u, orig_pixels[1][2]);
606  EXPECT_EQ(0u, orig_pixels[1][3]);
607  EXPECT_EQ(67u, orig_pixels[2][0]);
608  EXPECT_EQ(87u, orig_pixels[2][1]);
609  EXPECT_EQ(99u, orig_pixels[2][2]);
610  EXPECT_EQ(255u, orig_pixels[2][3]);
611  EXPECT_EQ(87u, orig_pixels[3][0]);
612  EXPECT_EQ(112u, orig_pixels[3][1]);
613  EXPECT_EQ(127u, orig_pixels[3][2]);
614  EXPECT_EQ(224u, orig_pixels[3][3]);
615
616  for (int i = 0; i < 1280; ++i) {
617    orig_pixels[i][0] = i;
618    orig_pixels[i][1] = i / 2;
619    orig_pixels[i][2] = i / 3;
620    orig_pixels[i][3] = i;
621  }
622  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
623    RGBColorMatrix(&orig_pixels[0][0], 0, &kRGBToSepia[0], 0, 0, 1280, 1);
624  }
625}
626
627TEST_F(LibYUVPlanarTest, TestARGBColorTable) {
628  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
629  memset(orig_pixels, 0, sizeof(orig_pixels));
630
631  // Matrix for Sepia.
632  static const uint8 kARGBTable[256 * 4] = {
633      1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u,
634  };
635
636  orig_pixels[0][0] = 0u;
637  orig_pixels[0][1] = 0u;
638  orig_pixels[0][2] = 0u;
639  orig_pixels[0][3] = 0u;
640  orig_pixels[1][0] = 1u;
641  orig_pixels[1][1] = 1u;
642  orig_pixels[1][2] = 1u;
643  orig_pixels[1][3] = 1u;
644  orig_pixels[2][0] = 2u;
645  orig_pixels[2][1] = 2u;
646  orig_pixels[2][2] = 2u;
647  orig_pixels[2][3] = 2u;
648  orig_pixels[3][0] = 0u;
649  orig_pixels[3][1] = 1u;
650  orig_pixels[3][2] = 2u;
651  orig_pixels[3][3] = 3u;
652  // Do 16 to test asm version.
653  ARGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 16, 1);
654  EXPECT_EQ(1u, orig_pixels[0][0]);
655  EXPECT_EQ(2u, orig_pixels[0][1]);
656  EXPECT_EQ(3u, orig_pixels[0][2]);
657  EXPECT_EQ(4u, orig_pixels[0][3]);
658  EXPECT_EQ(5u, orig_pixels[1][0]);
659  EXPECT_EQ(6u, orig_pixels[1][1]);
660  EXPECT_EQ(7u, orig_pixels[1][2]);
661  EXPECT_EQ(8u, orig_pixels[1][3]);
662  EXPECT_EQ(9u, orig_pixels[2][0]);
663  EXPECT_EQ(10u, orig_pixels[2][1]);
664  EXPECT_EQ(11u, orig_pixels[2][2]);
665  EXPECT_EQ(12u, orig_pixels[2][3]);
666  EXPECT_EQ(1u, orig_pixels[3][0]);
667  EXPECT_EQ(6u, orig_pixels[3][1]);
668  EXPECT_EQ(11u, orig_pixels[3][2]);
669  EXPECT_EQ(16u, orig_pixels[3][3]);
670
671  for (int i = 0; i < 1280; ++i) {
672    orig_pixels[i][0] = i;
673    orig_pixels[i][1] = i / 2;
674    orig_pixels[i][2] = i / 3;
675    orig_pixels[i][3] = i;
676  }
677  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
678    ARGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 1280, 1);
679  }
680}
681
682// Same as TestARGBColorTable except alpha does not change.
683TEST_F(LibYUVPlanarTest, TestRGBColorTable) {
684  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
685  memset(orig_pixels, 0, sizeof(orig_pixels));
686
687  // Matrix for Sepia.
688  static const uint8 kARGBTable[256 * 4] = {
689      1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u,
690  };
691
692  orig_pixels[0][0] = 0u;
693  orig_pixels[0][1] = 0u;
694  orig_pixels[0][2] = 0u;
695  orig_pixels[0][3] = 0u;
696  orig_pixels[1][0] = 1u;
697  orig_pixels[1][1] = 1u;
698  orig_pixels[1][2] = 1u;
699  orig_pixels[1][3] = 1u;
700  orig_pixels[2][0] = 2u;
701  orig_pixels[2][1] = 2u;
702  orig_pixels[2][2] = 2u;
703  orig_pixels[2][3] = 2u;
704  orig_pixels[3][0] = 0u;
705  orig_pixels[3][1] = 1u;
706  orig_pixels[3][2] = 2u;
707  orig_pixels[3][3] = 3u;
708  // Do 16 to test asm version.
709  RGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 16, 1);
710  EXPECT_EQ(1u, orig_pixels[0][0]);
711  EXPECT_EQ(2u, orig_pixels[0][1]);
712  EXPECT_EQ(3u, orig_pixels[0][2]);
713  EXPECT_EQ(0u, orig_pixels[0][3]);  // Alpha unchanged.
714  EXPECT_EQ(5u, orig_pixels[1][0]);
715  EXPECT_EQ(6u, orig_pixels[1][1]);
716  EXPECT_EQ(7u, orig_pixels[1][2]);
717  EXPECT_EQ(1u, orig_pixels[1][3]);  // Alpha unchanged.
718  EXPECT_EQ(9u, orig_pixels[2][0]);
719  EXPECT_EQ(10u, orig_pixels[2][1]);
720  EXPECT_EQ(11u, orig_pixels[2][2]);
721  EXPECT_EQ(2u, orig_pixels[2][3]);  // Alpha unchanged.
722  EXPECT_EQ(1u, orig_pixels[3][0]);
723  EXPECT_EQ(6u, orig_pixels[3][1]);
724  EXPECT_EQ(11u, orig_pixels[3][2]);
725  EXPECT_EQ(3u, orig_pixels[3][3]);  // Alpha unchanged.
726
727  for (int i = 0; i < 1280; ++i) {
728    orig_pixels[i][0] = i;
729    orig_pixels[i][1] = i / 2;
730    orig_pixels[i][2] = i / 3;
731    orig_pixels[i][3] = i;
732  }
733  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
734    RGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 1280, 1);
735  }
736}
737
738TEST_F(LibYUVPlanarTest, TestARGBQuantize) {
739  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
740
741  for (int i = 0; i < 1280; ++i) {
742    orig_pixels[i][0] = i;
743    orig_pixels[i][1] = i / 2;
744    orig_pixels[i][2] = i / 3;
745    orig_pixels[i][3] = i;
746  }
747  ARGBQuantize(&orig_pixels[0][0], 0, (65536 + (8 / 2)) / 8, 8, 8 / 2, 0, 0,
748               1280, 1);
749
750  for (int i = 0; i < 1280; ++i) {
751    EXPECT_EQ((i / 8 * 8 + 8 / 2) & 255, orig_pixels[i][0]);
752    EXPECT_EQ((i / 2 / 8 * 8 + 8 / 2) & 255, orig_pixels[i][1]);
753    EXPECT_EQ((i / 3 / 8 * 8 + 8 / 2) & 255, orig_pixels[i][2]);
754    EXPECT_EQ(i & 255, orig_pixels[i][3]);
755  }
756  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
757    ARGBQuantize(&orig_pixels[0][0], 0, (65536 + (8 / 2)) / 8, 8, 8 / 2, 0, 0,
758                 1280, 1);
759  }
760}
761
762TEST_F(LibYUVPlanarTest, TestARGBMirror) {
763  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
764  SIMD_ALIGNED(uint8 dst_pixels[1280][4]);
765
766  for (int i = 0; i < 1280; ++i) {
767    orig_pixels[i][0] = i;
768    orig_pixels[i][1] = i / 2;
769    orig_pixels[i][2] = i / 3;
770    orig_pixels[i][3] = i / 4;
771  }
772  ARGBMirror(&orig_pixels[0][0], 0, &dst_pixels[0][0], 0, 1280, 1);
773
774  for (int i = 0; i < 1280; ++i) {
775    EXPECT_EQ(i & 255, dst_pixels[1280 - 1 - i][0]);
776    EXPECT_EQ((i / 2) & 255, dst_pixels[1280 - 1 - i][1]);
777    EXPECT_EQ((i / 3) & 255, dst_pixels[1280 - 1 - i][2]);
778    EXPECT_EQ((i / 4) & 255, dst_pixels[1280 - 1 - i][3]);
779  }
780  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
781    ARGBMirror(&orig_pixels[0][0], 0, &dst_pixels[0][0], 0, 1280, 1);
782  }
783}
784
785TEST_F(LibYUVPlanarTest, TestShade) {
786  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
787  SIMD_ALIGNED(uint8 shade_pixels[1280][4]);
788  memset(orig_pixels, 0, sizeof(orig_pixels));
789
790  orig_pixels[0][0] = 10u;
791  orig_pixels[0][1] = 20u;
792  orig_pixels[0][2] = 40u;
793  orig_pixels[0][3] = 80u;
794  orig_pixels[1][0] = 0u;
795  orig_pixels[1][1] = 0u;
796  orig_pixels[1][2] = 0u;
797  orig_pixels[1][3] = 255u;
798  orig_pixels[2][0] = 0u;
799  orig_pixels[2][1] = 0u;
800  orig_pixels[2][2] = 0u;
801  orig_pixels[2][3] = 0u;
802  orig_pixels[3][0] = 0u;
803  orig_pixels[3][1] = 0u;
804  orig_pixels[3][2] = 0u;
805  orig_pixels[3][3] = 0u;
806  // Do 8 pixels to allow opt version to be used.
807  ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 8, 1, 0x80ffffff);
808  EXPECT_EQ(10u, shade_pixels[0][0]);
809  EXPECT_EQ(20u, shade_pixels[0][1]);
810  EXPECT_EQ(40u, shade_pixels[0][2]);
811  EXPECT_EQ(40u, shade_pixels[0][3]);
812  EXPECT_EQ(0u, shade_pixels[1][0]);
813  EXPECT_EQ(0u, shade_pixels[1][1]);
814  EXPECT_EQ(0u, shade_pixels[1][2]);
815  EXPECT_EQ(128u, shade_pixels[1][3]);
816  EXPECT_EQ(0u, shade_pixels[2][0]);
817  EXPECT_EQ(0u, shade_pixels[2][1]);
818  EXPECT_EQ(0u, shade_pixels[2][2]);
819  EXPECT_EQ(0u, shade_pixels[2][3]);
820  EXPECT_EQ(0u, shade_pixels[3][0]);
821  EXPECT_EQ(0u, shade_pixels[3][1]);
822  EXPECT_EQ(0u, shade_pixels[3][2]);
823  EXPECT_EQ(0u, shade_pixels[3][3]);
824
825  ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 8, 1, 0x80808080);
826  EXPECT_EQ(5u, shade_pixels[0][0]);
827  EXPECT_EQ(10u, shade_pixels[0][1]);
828  EXPECT_EQ(20u, shade_pixels[0][2]);
829  EXPECT_EQ(40u, shade_pixels[0][3]);
830
831  ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 8, 1, 0x10204080);
832  EXPECT_EQ(5u, shade_pixels[0][0]);
833  EXPECT_EQ(5u, shade_pixels[0][1]);
834  EXPECT_EQ(5u, shade_pixels[0][2]);
835  EXPECT_EQ(5u, shade_pixels[0][3]);
836
837  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
838    ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 1280, 1,
839              0x80808080);
840  }
841}
842
843TEST_F(LibYUVPlanarTest, TestARGBInterpolate) {
844  SIMD_ALIGNED(uint8 orig_pixels_0[1280][4]);
845  SIMD_ALIGNED(uint8 orig_pixels_1[1280][4]);
846  SIMD_ALIGNED(uint8 interpolate_pixels[1280][4]);
847  memset(orig_pixels_0, 0, sizeof(orig_pixels_0));
848  memset(orig_pixels_1, 0, sizeof(orig_pixels_1));
849
850  orig_pixels_0[0][0] = 16u;
851  orig_pixels_0[0][1] = 32u;
852  orig_pixels_0[0][2] = 64u;
853  orig_pixels_0[0][3] = 128u;
854  orig_pixels_0[1][0] = 0u;
855  orig_pixels_0[1][1] = 0u;
856  orig_pixels_0[1][2] = 0u;
857  orig_pixels_0[1][3] = 255u;
858  orig_pixels_0[2][0] = 0u;
859  orig_pixels_0[2][1] = 0u;
860  orig_pixels_0[2][2] = 0u;
861  orig_pixels_0[2][3] = 0u;
862  orig_pixels_0[3][0] = 0u;
863  orig_pixels_0[3][1] = 0u;
864  orig_pixels_0[3][2] = 0u;
865  orig_pixels_0[3][3] = 0u;
866
867  orig_pixels_1[0][0] = 0u;
868  orig_pixels_1[0][1] = 0u;
869  orig_pixels_1[0][2] = 0u;
870  orig_pixels_1[0][3] = 0u;
871  orig_pixels_1[1][0] = 0u;
872  orig_pixels_1[1][1] = 0u;
873  orig_pixels_1[1][2] = 0u;
874  orig_pixels_1[1][3] = 0u;
875  orig_pixels_1[2][0] = 0u;
876  orig_pixels_1[2][1] = 0u;
877  orig_pixels_1[2][2] = 0u;
878  orig_pixels_1[2][3] = 0u;
879  orig_pixels_1[3][0] = 255u;
880  orig_pixels_1[3][1] = 255u;
881  orig_pixels_1[3][2] = 255u;
882  orig_pixels_1[3][3] = 255u;
883
884  ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
885                  &interpolate_pixels[0][0], 0, 4, 1, 128);
886  EXPECT_EQ(8u, interpolate_pixels[0][0]);
887  EXPECT_EQ(16u, interpolate_pixels[0][1]);
888  EXPECT_EQ(32u, interpolate_pixels[0][2]);
889  EXPECT_EQ(64u, interpolate_pixels[0][3]);
890  EXPECT_EQ(0u, interpolate_pixels[1][0]);
891  EXPECT_EQ(0u, interpolate_pixels[1][1]);
892  EXPECT_EQ(0u, interpolate_pixels[1][2]);
893  EXPECT_EQ(128u, interpolate_pixels[1][3]);
894  EXPECT_EQ(0u, interpolate_pixels[2][0]);
895  EXPECT_EQ(0u, interpolate_pixels[2][1]);
896  EXPECT_EQ(0u, interpolate_pixels[2][2]);
897  EXPECT_EQ(0u, interpolate_pixels[2][3]);
898  EXPECT_EQ(128u, interpolate_pixels[3][0]);
899  EXPECT_EQ(128u, interpolate_pixels[3][1]);
900  EXPECT_EQ(128u, interpolate_pixels[3][2]);
901  EXPECT_EQ(128u, interpolate_pixels[3][3]);
902
903  ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
904                  &interpolate_pixels[0][0], 0, 4, 1, 0);
905  EXPECT_EQ(16u, interpolate_pixels[0][0]);
906  EXPECT_EQ(32u, interpolate_pixels[0][1]);
907  EXPECT_EQ(64u, interpolate_pixels[0][2]);
908  EXPECT_EQ(128u, interpolate_pixels[0][3]);
909
910  ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
911                  &interpolate_pixels[0][0], 0, 4, 1, 192);
912
913  EXPECT_EQ(4u, interpolate_pixels[0][0]);
914  EXPECT_EQ(8u, interpolate_pixels[0][1]);
915  EXPECT_EQ(16u, interpolate_pixels[0][2]);
916  EXPECT_EQ(32u, interpolate_pixels[0][3]);
917
918  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
919    ARGBInterpolate(&orig_pixels_0[0][0], 0, &orig_pixels_1[0][0], 0,
920                    &interpolate_pixels[0][0], 0, 1280, 1, 128);
921  }
922}
923
924TEST_F(LibYUVPlanarTest, TestInterpolatePlane) {
925  SIMD_ALIGNED(uint8 orig_pixels_0[1280]);
926  SIMD_ALIGNED(uint8 orig_pixels_1[1280]);
927  SIMD_ALIGNED(uint8 interpolate_pixels[1280]);
928  memset(orig_pixels_0, 0, sizeof(orig_pixels_0));
929  memset(orig_pixels_1, 0, sizeof(orig_pixels_1));
930
931  orig_pixels_0[0] = 16u;
932  orig_pixels_0[1] = 32u;
933  orig_pixels_0[2] = 64u;
934  orig_pixels_0[3] = 128u;
935  orig_pixels_0[4] = 0u;
936  orig_pixels_0[5] = 0u;
937  orig_pixels_0[6] = 0u;
938  orig_pixels_0[7] = 255u;
939  orig_pixels_0[8] = 0u;
940  orig_pixels_0[9] = 0u;
941  orig_pixels_0[10] = 0u;
942  orig_pixels_0[11] = 0u;
943  orig_pixels_0[12] = 0u;
944  orig_pixels_0[13] = 0u;
945  orig_pixels_0[14] = 0u;
946  orig_pixels_0[15] = 0u;
947
948  orig_pixels_1[0] = 0u;
949  orig_pixels_1[1] = 0u;
950  orig_pixels_1[2] = 0u;
951  orig_pixels_1[3] = 0u;
952  orig_pixels_1[4] = 0u;
953  orig_pixels_1[5] = 0u;
954  orig_pixels_1[6] = 0u;
955  orig_pixels_1[7] = 0u;
956  orig_pixels_1[8] = 0u;
957  orig_pixels_1[9] = 0u;
958  orig_pixels_1[10] = 0u;
959  orig_pixels_1[11] = 0u;
960  orig_pixels_1[12] = 255u;
961  orig_pixels_1[13] = 255u;
962  orig_pixels_1[14] = 255u;
963  orig_pixels_1[15] = 255u;
964
965  InterpolatePlane(&orig_pixels_0[0], 0, &orig_pixels_1[0], 0,
966                   &interpolate_pixels[0], 0, 16, 1, 128);
967  EXPECT_EQ(8u, interpolate_pixels[0]);
968  EXPECT_EQ(16u, interpolate_pixels[1]);
969  EXPECT_EQ(32u, interpolate_pixels[2]);
970  EXPECT_EQ(64u, interpolate_pixels[3]);
971  EXPECT_EQ(0u, interpolate_pixels[4]);
972  EXPECT_EQ(0u, interpolate_pixels[5]);
973  EXPECT_EQ(0u, interpolate_pixels[6]);
974  EXPECT_EQ(128u, interpolate_pixels[7]);
975  EXPECT_EQ(0u, interpolate_pixels[8]);
976  EXPECT_EQ(0u, interpolate_pixels[9]);
977  EXPECT_EQ(0u, interpolate_pixels[10]);
978  EXPECT_EQ(0u, interpolate_pixels[11]);
979  EXPECT_EQ(128u, interpolate_pixels[12]);
980  EXPECT_EQ(128u, interpolate_pixels[13]);
981  EXPECT_EQ(128u, interpolate_pixels[14]);
982  EXPECT_EQ(128u, interpolate_pixels[15]);
983
984  InterpolatePlane(&orig_pixels_0[0], 0, &orig_pixels_1[0], 0,
985                   &interpolate_pixels[0], 0, 16, 1, 0);
986  EXPECT_EQ(16u, interpolate_pixels[0]);
987  EXPECT_EQ(32u, interpolate_pixels[1]);
988  EXPECT_EQ(64u, interpolate_pixels[2]);
989  EXPECT_EQ(128u, interpolate_pixels[3]);
990
991  InterpolatePlane(&orig_pixels_0[0], 0, &orig_pixels_1[0], 0,
992                   &interpolate_pixels[0], 0, 16, 1, 192);
993
994  EXPECT_EQ(4u, interpolate_pixels[0]);
995  EXPECT_EQ(8u, interpolate_pixels[1]);
996  EXPECT_EQ(16u, interpolate_pixels[2]);
997  EXPECT_EQ(32u, interpolate_pixels[3]);
998
999  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1000    InterpolatePlane(&orig_pixels_0[0], 0, &orig_pixels_1[0], 0,
1001                     &interpolate_pixels[0], 0, 1280, 1, 123);
1002  }
1003}
1004
1005#define TESTTERP(FMT_A, BPP_A, STRIDE_A, FMT_B, BPP_B, STRIDE_B, W1280, TERP, \
1006                 N, NEG, OFF)                                                 \
1007  TEST_F(LibYUVPlanarTest, ARGBInterpolate##TERP##N) {                        \
1008    const int kWidth = ((W1280) > 0) ? (W1280) : 1;                           \
1009    const int kHeight = benchmark_height_;                                    \
1010    const int kStrideA =                                                      \
1011        (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;                \
1012    const int kStrideB =                                                      \
1013        (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;                \
1014    align_buffer_page_end(src_argb_a, kStrideA* kHeight + OFF);               \
1015    align_buffer_page_end(src_argb_b, kStrideA* kHeight + OFF);               \
1016    align_buffer_page_end(dst_argb_c, kStrideB* kHeight);                     \
1017    align_buffer_page_end(dst_argb_opt, kStrideB* kHeight);                   \
1018    for (int i = 0; i < kStrideA * kHeight; ++i) {                            \
1019      src_argb_a[i + OFF] = (fastrand() & 0xff);                              \
1020      src_argb_b[i + OFF] = (fastrand() & 0xff);                              \
1021    }                                                                         \
1022    MaskCpuFlags(disable_cpu_flags_);                                         \
1023    ARGBInterpolate(src_argb_a + OFF, kStrideA, src_argb_b + OFF, kStrideA,   \
1024                    dst_argb_c, kStrideB, kWidth, NEG kHeight, TERP);         \
1025    MaskCpuFlags(benchmark_cpu_info_);                                        \
1026    for (int i = 0; i < benchmark_iterations_; ++i) {                         \
1027      ARGBInterpolate(src_argb_a + OFF, kStrideA, src_argb_b + OFF, kStrideA, \
1028                      dst_argb_opt, kStrideB, kWidth, NEG kHeight, TERP);     \
1029    }                                                                         \
1030    for (int i = 0; i < kStrideB * kHeight; ++i) {                            \
1031      EXPECT_EQ(dst_argb_c[i], dst_argb_opt[i]);                              \
1032    }                                                                         \
1033    free_aligned_buffer_page_end(src_argb_a);                                 \
1034    free_aligned_buffer_page_end(src_argb_b);                                 \
1035    free_aligned_buffer_page_end(dst_argb_c);                                 \
1036    free_aligned_buffer_page_end(dst_argb_opt);                               \
1037  }
1038
1039#define TESTINTERPOLATE(TERP)                                                \
1040  TESTTERP(ARGB, 4, 1, ARGB, 4, 1, benchmark_width_ - 1, TERP, _Any, +, 0)   \
1041  TESTTERP(ARGB, 4, 1, ARGB, 4, 1, benchmark_width_, TERP, _Unaligned, +, 1) \
1042  TESTTERP(ARGB, 4, 1, ARGB, 4, 1, benchmark_width_, TERP, _Invert, -, 0)    \
1043  TESTTERP(ARGB, 4, 1, ARGB, 4, 1, benchmark_width_, TERP, _Opt, +, 0)
1044
1045TESTINTERPOLATE(0)
1046TESTINTERPOLATE(64)
1047TESTINTERPOLATE(128)
1048TESTINTERPOLATE(192)
1049TESTINTERPOLATE(255)
1050
1051static int TestBlend(int width,
1052                     int height,
1053                     int benchmark_iterations,
1054                     int disable_cpu_flags,
1055                     int benchmark_cpu_info,
1056                     int invert,
1057                     int off) {
1058  if (width < 1) {
1059    width = 1;
1060  }
1061  const int kBpp = 4;
1062  const int kStride = width * kBpp;
1063  align_buffer_page_end(src_argb_a, kStride * height + off);
1064  align_buffer_page_end(src_argb_b, kStride * height + off);
1065  align_buffer_page_end(dst_argb_c, kStride * height);
1066  align_buffer_page_end(dst_argb_opt, kStride * height);
1067  for (int i = 0; i < kStride * height; ++i) {
1068    src_argb_a[i + off] = (fastrand() & 0xff);
1069    src_argb_b[i + off] = (fastrand() & 0xff);
1070  }
1071  ARGBAttenuate(src_argb_a + off, kStride, src_argb_a + off, kStride, width,
1072                height);
1073  ARGBAttenuate(src_argb_b + off, kStride, src_argb_b + off, kStride, width,
1074                height);
1075  memset(dst_argb_c, 255, kStride * height);
1076  memset(dst_argb_opt, 255, kStride * height);
1077
1078  MaskCpuFlags(disable_cpu_flags);
1079  ARGBBlend(src_argb_a + off, kStride, src_argb_b + off, kStride, dst_argb_c,
1080            kStride, width, invert * height);
1081  MaskCpuFlags(benchmark_cpu_info);
1082  for (int i = 0; i < benchmark_iterations; ++i) {
1083    ARGBBlend(src_argb_a + off, kStride, src_argb_b + off, kStride,
1084              dst_argb_opt, kStride, width, invert * height);
1085  }
1086  int max_diff = 0;
1087  for (int i = 0; i < kStride * height; ++i) {
1088    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1089                       static_cast<int>(dst_argb_opt[i]));
1090    if (abs_diff > max_diff) {
1091      max_diff = abs_diff;
1092    }
1093  }
1094  free_aligned_buffer_page_end(src_argb_a);
1095  free_aligned_buffer_page_end(src_argb_b);
1096  free_aligned_buffer_page_end(dst_argb_c);
1097  free_aligned_buffer_page_end(dst_argb_opt);
1098  return max_diff;
1099}
1100
1101TEST_F(LibYUVPlanarTest, ARGBBlend_Any) {
1102  int max_diff =
1103      TestBlend(benchmark_width_ - 4, benchmark_height_, benchmark_iterations_,
1104                disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1105  EXPECT_LE(max_diff, 1);
1106}
1107
1108TEST_F(LibYUVPlanarTest, ARGBBlend_Unaligned) {
1109  int max_diff =
1110      TestBlend(benchmark_width_, benchmark_height_, benchmark_iterations_,
1111                disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1112  EXPECT_LE(max_diff, 1);
1113}
1114
1115TEST_F(LibYUVPlanarTest, ARGBBlend_Invert) {
1116  int max_diff =
1117      TestBlend(benchmark_width_, benchmark_height_, benchmark_iterations_,
1118                disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1119  EXPECT_LE(max_diff, 1);
1120}
1121
1122TEST_F(LibYUVPlanarTest, ARGBBlend_Opt) {
1123  int max_diff =
1124      TestBlend(benchmark_width_, benchmark_height_, benchmark_iterations_,
1125                disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1126  EXPECT_LE(max_diff, 1);
1127}
1128
1129static void TestBlendPlane(int width,
1130                           int height,
1131                           int benchmark_iterations,
1132                           int disable_cpu_flags,
1133                           int benchmark_cpu_info,
1134                           int invert,
1135                           int off) {
1136  if (width < 1) {
1137    width = 1;
1138  }
1139  const int kBpp = 1;
1140  const int kStride = width * kBpp;
1141  align_buffer_page_end(src_argb_a, kStride * height + off);
1142  align_buffer_page_end(src_argb_b, kStride * height + off);
1143  align_buffer_page_end(src_argb_alpha, kStride * height + off);
1144  align_buffer_page_end(dst_argb_c, kStride * height + off);
1145  align_buffer_page_end(dst_argb_opt, kStride * height + off);
1146  memset(dst_argb_c, 255, kStride * height + off);
1147  memset(dst_argb_opt, 255, kStride * height + off);
1148
1149  // Test source is maintained exactly if alpha is 255.
1150  for (int i = 0; i < width; ++i) {
1151    src_argb_a[i + off] = i & 255;
1152    src_argb_b[i + off] = 255 - (i & 255);
1153  }
1154  memset(src_argb_alpha + off, 255, width);
1155  BlendPlane(src_argb_a + off, width, src_argb_b + off, width,
1156             src_argb_alpha + off, width, dst_argb_opt + off, width, width, 1);
1157  for (int i = 0; i < width; ++i) {
1158    EXPECT_EQ(src_argb_a[i + off], dst_argb_opt[i + off]);
1159  }
1160  // Test destination is maintained exactly if alpha is 0.
1161  memset(src_argb_alpha + off, 0, width);
1162  BlendPlane(src_argb_a + off, width, src_argb_b + off, width,
1163             src_argb_alpha + off, width, dst_argb_opt + off, width, width, 1);
1164  for (int i = 0; i < width; ++i) {
1165    EXPECT_EQ(src_argb_b[i + off], dst_argb_opt[i + off]);
1166  }
1167  for (int i = 0; i < kStride * height; ++i) {
1168    src_argb_a[i + off] = (fastrand() & 0xff);
1169    src_argb_b[i + off] = (fastrand() & 0xff);
1170    src_argb_alpha[i + off] = (fastrand() & 0xff);
1171  }
1172
1173  MaskCpuFlags(disable_cpu_flags);
1174  BlendPlane(src_argb_a + off, width, src_argb_b + off, width,
1175             src_argb_alpha + off, width, dst_argb_c + off, width, width,
1176             invert * height);
1177  MaskCpuFlags(benchmark_cpu_info);
1178  for (int i = 0; i < benchmark_iterations; ++i) {
1179    BlendPlane(src_argb_a + off, width, src_argb_b + off, width,
1180               src_argb_alpha + off, width, dst_argb_opt + off, width, width,
1181               invert * height);
1182  }
1183  for (int i = 0; i < kStride * height; ++i) {
1184    EXPECT_EQ(dst_argb_c[i + off], dst_argb_opt[i + off]);
1185  }
1186  free_aligned_buffer_page_end(src_argb_a);
1187  free_aligned_buffer_page_end(src_argb_b);
1188  free_aligned_buffer_page_end(src_argb_alpha);
1189  free_aligned_buffer_page_end(dst_argb_c);
1190  free_aligned_buffer_page_end(dst_argb_opt);
1191  return;
1192}
1193
1194TEST_F(LibYUVPlanarTest, BlendPlane_Opt) {
1195  TestBlendPlane(benchmark_width_, benchmark_height_, benchmark_iterations_,
1196                 disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1197}
1198TEST_F(LibYUVPlanarTest, BlendPlane_Unaligned) {
1199  TestBlendPlane(benchmark_width_, benchmark_height_, benchmark_iterations_,
1200                 disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1201}
1202TEST_F(LibYUVPlanarTest, BlendPlane_Any) {
1203  TestBlendPlane(benchmark_width_ - 4, benchmark_height_, benchmark_iterations_,
1204                 disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1205}
1206TEST_F(LibYUVPlanarTest, BlendPlane_Invert) {
1207  TestBlendPlane(benchmark_width_, benchmark_height_, benchmark_iterations_,
1208                 disable_cpu_flags_, benchmark_cpu_info_, -1, 1);
1209}
1210
1211#define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a))
1212
1213static void TestI420Blend(int width,
1214                          int height,
1215                          int benchmark_iterations,
1216                          int disable_cpu_flags,
1217                          int benchmark_cpu_info,
1218                          int invert,
1219                          int off) {
1220  width = ((width) > 0) ? (width) : 1;
1221  const int kStrideUV = SUBSAMPLE(width, 2);
1222  const int kSizeUV = kStrideUV * SUBSAMPLE(height, 2);
1223  align_buffer_page_end(src_y0, width * height + off);
1224  align_buffer_page_end(src_u0, kSizeUV + off);
1225  align_buffer_page_end(src_v0, kSizeUV + off);
1226  align_buffer_page_end(src_y1, width * height + off);
1227  align_buffer_page_end(src_u1, kSizeUV + off);
1228  align_buffer_page_end(src_v1, kSizeUV + off);
1229  align_buffer_page_end(src_a, width * height + off);
1230  align_buffer_page_end(dst_y_c, width * height + off);
1231  align_buffer_page_end(dst_u_c, kSizeUV + off);
1232  align_buffer_page_end(dst_v_c, kSizeUV + off);
1233  align_buffer_page_end(dst_y_opt, width * height + off);
1234  align_buffer_page_end(dst_u_opt, kSizeUV + off);
1235  align_buffer_page_end(dst_v_opt, kSizeUV + off);
1236
1237  MemRandomize(src_y0, width * height + off);
1238  MemRandomize(src_u0, kSizeUV + off);
1239  MemRandomize(src_v0, kSizeUV + off);
1240  MemRandomize(src_y1, width * height + off);
1241  MemRandomize(src_u1, kSizeUV + off);
1242  MemRandomize(src_v1, kSizeUV + off);
1243  MemRandomize(src_a, width * height + off);
1244  memset(dst_y_c, 255, width * height + off);
1245  memset(dst_u_c, 255, kSizeUV + off);
1246  memset(dst_v_c, 255, kSizeUV + off);
1247  memset(dst_y_opt, 255, width * height + off);
1248  memset(dst_u_opt, 255, kSizeUV + off);
1249  memset(dst_v_opt, 255, kSizeUV + off);
1250
1251  MaskCpuFlags(disable_cpu_flags);
1252  I420Blend(src_y0 + off, width, src_u0 + off, kStrideUV, src_v0 + off,
1253            kStrideUV, src_y1 + off, width, src_u1 + off, kStrideUV,
1254            src_v1 + off, kStrideUV, src_a + off, width, dst_y_c + off, width,
1255            dst_u_c + off, kStrideUV, dst_v_c + off, kStrideUV, width,
1256            invert * height);
1257  MaskCpuFlags(benchmark_cpu_info);
1258  for (int i = 0; i < benchmark_iterations; ++i) {
1259    I420Blend(src_y0 + off, width, src_u0 + off, kStrideUV, src_v0 + off,
1260              kStrideUV, src_y1 + off, width, src_u1 + off, kStrideUV,
1261              src_v1 + off, kStrideUV, src_a + off, width, dst_y_opt + off,
1262              width, dst_u_opt + off, kStrideUV, dst_v_opt + off, kStrideUV,
1263              width, invert * height);
1264  }
1265  for (int i = 0; i < width * height; ++i) {
1266    EXPECT_EQ(dst_y_c[i + off], dst_y_opt[i + off]);
1267  }
1268  for (int i = 0; i < kSizeUV; ++i) {
1269    EXPECT_EQ(dst_u_c[i + off], dst_u_opt[i + off]);
1270    EXPECT_EQ(dst_v_c[i + off], dst_v_opt[i + off]);
1271  }
1272  free_aligned_buffer_page_end(src_y0);
1273  free_aligned_buffer_page_end(src_u0);
1274  free_aligned_buffer_page_end(src_v0);
1275  free_aligned_buffer_page_end(src_y1);
1276  free_aligned_buffer_page_end(src_u1);
1277  free_aligned_buffer_page_end(src_v1);
1278  free_aligned_buffer_page_end(src_a);
1279  free_aligned_buffer_page_end(dst_y_c);
1280  free_aligned_buffer_page_end(dst_u_c);
1281  free_aligned_buffer_page_end(dst_v_c);
1282  free_aligned_buffer_page_end(dst_y_opt);
1283  free_aligned_buffer_page_end(dst_u_opt);
1284  free_aligned_buffer_page_end(dst_v_opt);
1285  return;
1286}
1287
1288TEST_F(LibYUVPlanarTest, I420Blend_Opt) {
1289  TestI420Blend(benchmark_width_, benchmark_height_, benchmark_iterations_,
1290                disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1291}
1292TEST_F(LibYUVPlanarTest, I420Blend_Unaligned) {
1293  TestI420Blend(benchmark_width_, benchmark_height_, benchmark_iterations_,
1294                disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1295}
1296
1297// TODO(fbarchard): DISABLED because _Any uses C.  Avoid C and re-enable.
1298TEST_F(LibYUVPlanarTest, DISABLED_I420Blend_Any) {
1299  TestI420Blend(benchmark_width_ - 4, benchmark_height_, benchmark_iterations_,
1300                disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1301}
1302TEST_F(LibYUVPlanarTest, I420Blend_Invert) {
1303  TestI420Blend(benchmark_width_, benchmark_height_, benchmark_iterations_,
1304                disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1305}
1306
1307TEST_F(LibYUVPlanarTest, TestAffine) {
1308  SIMD_ALIGNED(uint8 orig_pixels_0[1280][4]);
1309  SIMD_ALIGNED(uint8 interpolate_pixels_C[1280][4]);
1310
1311  for (int i = 0; i < 1280; ++i) {
1312    for (int j = 0; j < 4; ++j) {
1313      orig_pixels_0[i][j] = i;
1314    }
1315  }
1316
1317  float uv_step[4] = {0.f, 0.f, 0.75f, 0.f};
1318
1319  ARGBAffineRow_C(&orig_pixels_0[0][0], 0, &interpolate_pixels_C[0][0], uv_step,
1320                  1280);
1321  EXPECT_EQ(0u, interpolate_pixels_C[0][0]);
1322  EXPECT_EQ(96u, interpolate_pixels_C[128][0]);
1323  EXPECT_EQ(191u, interpolate_pixels_C[255][3]);
1324
1325#if defined(HAS_ARGBAFFINEROW_SSE2)
1326  SIMD_ALIGNED(uint8 interpolate_pixels_Opt[1280][4]);
1327  ARGBAffineRow_SSE2(&orig_pixels_0[0][0], 0, &interpolate_pixels_Opt[0][0],
1328                     uv_step, 1280);
1329  EXPECT_EQ(0, memcmp(interpolate_pixels_Opt, interpolate_pixels_C, 1280 * 4));
1330
1331  int has_sse2 = TestCpuFlag(kCpuHasSSE2);
1332  if (has_sse2) {
1333    for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1334      ARGBAffineRow_SSE2(&orig_pixels_0[0][0], 0, &interpolate_pixels_Opt[0][0],
1335                         uv_step, 1280);
1336    }
1337  }
1338#endif
1339}
1340
1341TEST_F(LibYUVPlanarTest, TestCopyPlane) {
1342  int err = 0;
1343  int yw = benchmark_width_;
1344  int yh = benchmark_height_;
1345  int b = 12;
1346  int i, j;
1347
1348  int y_plane_size = (yw + b * 2) * (yh + b * 2);
1349  align_buffer_page_end(orig_y, y_plane_size);
1350  align_buffer_page_end(dst_c, y_plane_size);
1351  align_buffer_page_end(dst_opt, y_plane_size);
1352
1353  memset(orig_y, 0, y_plane_size);
1354  memset(dst_c, 0, y_plane_size);
1355  memset(dst_opt, 0, y_plane_size);
1356
1357  // Fill image buffers with random data.
1358  for (i = b; i < (yh + b); ++i) {
1359    for (j = b; j < (yw + b); ++j) {
1360      orig_y[i * (yw + b * 2) + j] = fastrand() & 0xff;
1361    }
1362  }
1363
1364  // Fill destination buffers with random data.
1365  for (i = 0; i < y_plane_size; ++i) {
1366    uint8 random_number = fastrand() & 0x7f;
1367    dst_c[i] = random_number;
1368    dst_opt[i] = dst_c[i];
1369  }
1370
1371  int y_off = b * (yw + b * 2) + b;
1372
1373  int y_st = yw + b * 2;
1374  int stride = 8;
1375
1376  // Disable all optimizations.
1377  MaskCpuFlags(disable_cpu_flags_);
1378  for (j = 0; j < benchmark_iterations_; j++) {
1379    CopyPlane(orig_y + y_off, y_st, dst_c + y_off, stride, yw, yh);
1380  }
1381
1382  // Enable optimizations.
1383  MaskCpuFlags(benchmark_cpu_info_);
1384  for (j = 0; j < benchmark_iterations_; j++) {
1385    CopyPlane(orig_y + y_off, y_st, dst_opt + y_off, stride, yw, yh);
1386  }
1387
1388  for (i = 0; i < y_plane_size; ++i) {
1389    if (dst_c[i] != dst_opt[i])
1390      ++err;
1391  }
1392
1393  free_aligned_buffer_page_end(orig_y);
1394  free_aligned_buffer_page_end(dst_c);
1395  free_aligned_buffer_page_end(dst_opt);
1396
1397  EXPECT_EQ(0, err);
1398}
1399
1400static int TestMultiply(int width,
1401                        int height,
1402                        int benchmark_iterations,
1403                        int disable_cpu_flags,
1404                        int benchmark_cpu_info,
1405                        int invert,
1406                        int off) {
1407  if (width < 1) {
1408    width = 1;
1409  }
1410  const int kBpp = 4;
1411  const int kStride = width * kBpp;
1412  align_buffer_page_end(src_argb_a, kStride * height + off);
1413  align_buffer_page_end(src_argb_b, kStride * height + off);
1414  align_buffer_page_end(dst_argb_c, kStride * height);
1415  align_buffer_page_end(dst_argb_opt, kStride * height);
1416  for (int i = 0; i < kStride * height; ++i) {
1417    src_argb_a[i + off] = (fastrand() & 0xff);
1418    src_argb_b[i + off] = (fastrand() & 0xff);
1419  }
1420  memset(dst_argb_c, 0, kStride * height);
1421  memset(dst_argb_opt, 0, kStride * height);
1422
1423  MaskCpuFlags(disable_cpu_flags);
1424  ARGBMultiply(src_argb_a + off, kStride, src_argb_b + off, kStride, dst_argb_c,
1425               kStride, width, invert * height);
1426  MaskCpuFlags(benchmark_cpu_info);
1427  for (int i = 0; i < benchmark_iterations; ++i) {
1428    ARGBMultiply(src_argb_a + off, kStride, src_argb_b + off, kStride,
1429                 dst_argb_opt, kStride, width, invert * height);
1430  }
1431  int max_diff = 0;
1432  for (int i = 0; i < kStride * height; ++i) {
1433    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1434                       static_cast<int>(dst_argb_opt[i]));
1435    if (abs_diff > max_diff) {
1436      max_diff = abs_diff;
1437    }
1438  }
1439  free_aligned_buffer_page_end(src_argb_a);
1440  free_aligned_buffer_page_end(src_argb_b);
1441  free_aligned_buffer_page_end(dst_argb_c);
1442  free_aligned_buffer_page_end(dst_argb_opt);
1443  return max_diff;
1444}
1445
1446TEST_F(LibYUVPlanarTest, ARGBMultiply_Any) {
1447  int max_diff = TestMultiply(benchmark_width_ - 1, benchmark_height_,
1448                              benchmark_iterations_, disable_cpu_flags_,
1449                              benchmark_cpu_info_, +1, 0);
1450  EXPECT_LE(max_diff, 1);
1451}
1452
1453TEST_F(LibYUVPlanarTest, ARGBMultiply_Unaligned) {
1454  int max_diff =
1455      TestMultiply(benchmark_width_, benchmark_height_, benchmark_iterations_,
1456                   disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1457  EXPECT_LE(max_diff, 1);
1458}
1459
1460TEST_F(LibYUVPlanarTest, ARGBMultiply_Invert) {
1461  int max_diff =
1462      TestMultiply(benchmark_width_, benchmark_height_, benchmark_iterations_,
1463                   disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1464  EXPECT_LE(max_diff, 1);
1465}
1466
1467TEST_F(LibYUVPlanarTest, ARGBMultiply_Opt) {
1468  int max_diff =
1469      TestMultiply(benchmark_width_, benchmark_height_, benchmark_iterations_,
1470                   disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1471  EXPECT_LE(max_diff, 1);
1472}
1473
1474static int TestAdd(int width,
1475                   int height,
1476                   int benchmark_iterations,
1477                   int disable_cpu_flags,
1478                   int benchmark_cpu_info,
1479                   int invert,
1480                   int off) {
1481  if (width < 1) {
1482    width = 1;
1483  }
1484  const int kBpp = 4;
1485  const int kStride = width * kBpp;
1486  align_buffer_page_end(src_argb_a, kStride * height + off);
1487  align_buffer_page_end(src_argb_b, kStride * height + off);
1488  align_buffer_page_end(dst_argb_c, kStride * height);
1489  align_buffer_page_end(dst_argb_opt, kStride * height);
1490  for (int i = 0; i < kStride * height; ++i) {
1491    src_argb_a[i + off] = (fastrand() & 0xff);
1492    src_argb_b[i + off] = (fastrand() & 0xff);
1493  }
1494  memset(dst_argb_c, 0, kStride * height);
1495  memset(dst_argb_opt, 0, kStride * height);
1496
1497  MaskCpuFlags(disable_cpu_flags);
1498  ARGBAdd(src_argb_a + off, kStride, src_argb_b + off, kStride, dst_argb_c,
1499          kStride, width, invert * height);
1500  MaskCpuFlags(benchmark_cpu_info);
1501  for (int i = 0; i < benchmark_iterations; ++i) {
1502    ARGBAdd(src_argb_a + off, kStride, src_argb_b + off, kStride, dst_argb_opt,
1503            kStride, width, invert * height);
1504  }
1505  int max_diff = 0;
1506  for (int i = 0; i < kStride * height; ++i) {
1507    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1508                       static_cast<int>(dst_argb_opt[i]));
1509    if (abs_diff > max_diff) {
1510      max_diff = abs_diff;
1511    }
1512  }
1513  free_aligned_buffer_page_end(src_argb_a);
1514  free_aligned_buffer_page_end(src_argb_b);
1515  free_aligned_buffer_page_end(dst_argb_c);
1516  free_aligned_buffer_page_end(dst_argb_opt);
1517  return max_diff;
1518}
1519
1520TEST_F(LibYUVPlanarTest, ARGBAdd_Any) {
1521  int max_diff =
1522      TestAdd(benchmark_width_ - 1, benchmark_height_, benchmark_iterations_,
1523              disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1524  EXPECT_LE(max_diff, 1);
1525}
1526
1527TEST_F(LibYUVPlanarTest, ARGBAdd_Unaligned) {
1528  int max_diff =
1529      TestAdd(benchmark_width_, benchmark_height_, benchmark_iterations_,
1530              disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1531  EXPECT_LE(max_diff, 1);
1532}
1533
1534TEST_F(LibYUVPlanarTest, ARGBAdd_Invert) {
1535  int max_diff =
1536      TestAdd(benchmark_width_, benchmark_height_, benchmark_iterations_,
1537              disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1538  EXPECT_LE(max_diff, 1);
1539}
1540
1541TEST_F(LibYUVPlanarTest, ARGBAdd_Opt) {
1542  int max_diff =
1543      TestAdd(benchmark_width_, benchmark_height_, benchmark_iterations_,
1544              disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1545  EXPECT_LE(max_diff, 1);
1546}
1547
1548static int TestSubtract(int width,
1549                        int height,
1550                        int benchmark_iterations,
1551                        int disable_cpu_flags,
1552                        int benchmark_cpu_info,
1553                        int invert,
1554                        int off) {
1555  if (width < 1) {
1556    width = 1;
1557  }
1558  const int kBpp = 4;
1559  const int kStride = width * kBpp;
1560  align_buffer_page_end(src_argb_a, kStride * height + off);
1561  align_buffer_page_end(src_argb_b, kStride * height + off);
1562  align_buffer_page_end(dst_argb_c, kStride * height);
1563  align_buffer_page_end(dst_argb_opt, kStride * height);
1564  for (int i = 0; i < kStride * height; ++i) {
1565    src_argb_a[i + off] = (fastrand() & 0xff);
1566    src_argb_b[i + off] = (fastrand() & 0xff);
1567  }
1568  memset(dst_argb_c, 0, kStride * height);
1569  memset(dst_argb_opt, 0, kStride * height);
1570
1571  MaskCpuFlags(disable_cpu_flags);
1572  ARGBSubtract(src_argb_a + off, kStride, src_argb_b + off, kStride, dst_argb_c,
1573               kStride, width, invert * height);
1574  MaskCpuFlags(benchmark_cpu_info);
1575  for (int i = 0; i < benchmark_iterations; ++i) {
1576    ARGBSubtract(src_argb_a + off, kStride, src_argb_b + off, kStride,
1577                 dst_argb_opt, kStride, width, invert * height);
1578  }
1579  int max_diff = 0;
1580  for (int i = 0; i < kStride * height; ++i) {
1581    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1582                       static_cast<int>(dst_argb_opt[i]));
1583    if (abs_diff > max_diff) {
1584      max_diff = abs_diff;
1585    }
1586  }
1587  free_aligned_buffer_page_end(src_argb_a);
1588  free_aligned_buffer_page_end(src_argb_b);
1589  free_aligned_buffer_page_end(dst_argb_c);
1590  free_aligned_buffer_page_end(dst_argb_opt);
1591  return max_diff;
1592}
1593
1594TEST_F(LibYUVPlanarTest, ARGBSubtract_Any) {
1595  int max_diff = TestSubtract(benchmark_width_ - 1, benchmark_height_,
1596                              benchmark_iterations_, disable_cpu_flags_,
1597                              benchmark_cpu_info_, +1, 0);
1598  EXPECT_LE(max_diff, 1);
1599}
1600
1601TEST_F(LibYUVPlanarTest, ARGBSubtract_Unaligned) {
1602  int max_diff =
1603      TestSubtract(benchmark_width_, benchmark_height_, benchmark_iterations_,
1604                   disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1605  EXPECT_LE(max_diff, 1);
1606}
1607
1608TEST_F(LibYUVPlanarTest, ARGBSubtract_Invert) {
1609  int max_diff =
1610      TestSubtract(benchmark_width_, benchmark_height_, benchmark_iterations_,
1611                   disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1612  EXPECT_LE(max_diff, 1);
1613}
1614
1615TEST_F(LibYUVPlanarTest, ARGBSubtract_Opt) {
1616  int max_diff =
1617      TestSubtract(benchmark_width_, benchmark_height_, benchmark_iterations_,
1618                   disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1619  EXPECT_LE(max_diff, 1);
1620}
1621
1622static int TestSobel(int width,
1623                     int height,
1624                     int benchmark_iterations,
1625                     int disable_cpu_flags,
1626                     int benchmark_cpu_info,
1627                     int invert,
1628                     int off) {
1629  if (width < 1) {
1630    width = 1;
1631  }
1632  const int kBpp = 4;
1633  const int kStride = width * kBpp;
1634  align_buffer_page_end(src_argb_a, kStride * height + off);
1635  align_buffer_page_end(dst_argb_c, kStride * height);
1636  align_buffer_page_end(dst_argb_opt, kStride * height);
1637  memset(src_argb_a, 0, kStride * height + off);
1638  for (int i = 0; i < kStride * height; ++i) {
1639    src_argb_a[i + off] = (fastrand() & 0xff);
1640  }
1641  memset(dst_argb_c, 0, kStride * height);
1642  memset(dst_argb_opt, 0, kStride * height);
1643
1644  MaskCpuFlags(disable_cpu_flags);
1645  ARGBSobel(src_argb_a + off, kStride, dst_argb_c, kStride, width,
1646            invert * height);
1647  MaskCpuFlags(benchmark_cpu_info);
1648  for (int i = 0; i < benchmark_iterations; ++i) {
1649    ARGBSobel(src_argb_a + off, kStride, dst_argb_opt, kStride, width,
1650              invert * height);
1651  }
1652  int max_diff = 0;
1653  for (int i = 0; i < kStride * height; ++i) {
1654    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1655                       static_cast<int>(dst_argb_opt[i]));
1656    if (abs_diff > max_diff) {
1657      max_diff = abs_diff;
1658    }
1659  }
1660  free_aligned_buffer_page_end(src_argb_a);
1661  free_aligned_buffer_page_end(dst_argb_c);
1662  free_aligned_buffer_page_end(dst_argb_opt);
1663  return max_diff;
1664}
1665
1666TEST_F(LibYUVPlanarTest, ARGBSobel_Any) {
1667  int max_diff =
1668      TestSobel(benchmark_width_ - 1, benchmark_height_, benchmark_iterations_,
1669                disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1670  EXPECT_EQ(0, max_diff);
1671}
1672
1673TEST_F(LibYUVPlanarTest, ARGBSobel_Unaligned) {
1674  int max_diff =
1675      TestSobel(benchmark_width_, benchmark_height_, benchmark_iterations_,
1676                disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1677  EXPECT_EQ(0, max_diff);
1678}
1679
1680TEST_F(LibYUVPlanarTest, ARGBSobel_Invert) {
1681  int max_diff =
1682      TestSobel(benchmark_width_, benchmark_height_, benchmark_iterations_,
1683                disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1684  EXPECT_EQ(0, max_diff);
1685}
1686
1687TEST_F(LibYUVPlanarTest, ARGBSobel_Opt) {
1688  int max_diff =
1689      TestSobel(benchmark_width_, benchmark_height_, benchmark_iterations_,
1690                disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1691  EXPECT_EQ(0, max_diff);
1692}
1693
1694static int TestSobelToPlane(int width,
1695                            int height,
1696                            int benchmark_iterations,
1697                            int disable_cpu_flags,
1698                            int benchmark_cpu_info,
1699                            int invert,
1700                            int off) {
1701  if (width < 1) {
1702    width = 1;
1703  }
1704  const int kSrcBpp = 4;
1705  const int kDstBpp = 1;
1706  const int kSrcStride = (width * kSrcBpp + 15) & ~15;
1707  const int kDstStride = (width * kDstBpp + 15) & ~15;
1708  align_buffer_page_end(src_argb_a, kSrcStride * height + off);
1709  align_buffer_page_end(dst_argb_c, kDstStride * height);
1710  align_buffer_page_end(dst_argb_opt, kDstStride * height);
1711  memset(src_argb_a, 0, kSrcStride * height + off);
1712  for (int i = 0; i < kSrcStride * height; ++i) {
1713    src_argb_a[i + off] = (fastrand() & 0xff);
1714  }
1715  memset(dst_argb_c, 0, kDstStride * height);
1716  memset(dst_argb_opt, 0, kDstStride * height);
1717
1718  MaskCpuFlags(disable_cpu_flags);
1719  ARGBSobelToPlane(src_argb_a + off, kSrcStride, dst_argb_c, kDstStride, width,
1720                   invert * height);
1721  MaskCpuFlags(benchmark_cpu_info);
1722  for (int i = 0; i < benchmark_iterations; ++i) {
1723    ARGBSobelToPlane(src_argb_a + off, kSrcStride, dst_argb_opt, kDstStride,
1724                     width, invert * height);
1725  }
1726  int max_diff = 0;
1727  for (int i = 0; i < kDstStride * height; ++i) {
1728    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1729                       static_cast<int>(dst_argb_opt[i]));
1730    if (abs_diff > max_diff) {
1731      max_diff = abs_diff;
1732    }
1733  }
1734  free_aligned_buffer_page_end(src_argb_a);
1735  free_aligned_buffer_page_end(dst_argb_c);
1736  free_aligned_buffer_page_end(dst_argb_opt);
1737  return max_diff;
1738}
1739
1740TEST_F(LibYUVPlanarTest, ARGBSobelToPlane_Any) {
1741  int max_diff = TestSobelToPlane(benchmark_width_ - 1, benchmark_height_,
1742                                  benchmark_iterations_, disable_cpu_flags_,
1743                                  benchmark_cpu_info_, +1, 0);
1744  EXPECT_EQ(0, max_diff);
1745}
1746
1747TEST_F(LibYUVPlanarTest, ARGBSobelToPlane_Unaligned) {
1748  int max_diff = TestSobelToPlane(benchmark_width_, benchmark_height_,
1749                                  benchmark_iterations_, disable_cpu_flags_,
1750                                  benchmark_cpu_info_, +1, 1);
1751  EXPECT_EQ(0, max_diff);
1752}
1753
1754TEST_F(LibYUVPlanarTest, ARGBSobelToPlane_Invert) {
1755  int max_diff = TestSobelToPlane(benchmark_width_, benchmark_height_,
1756                                  benchmark_iterations_, disable_cpu_flags_,
1757                                  benchmark_cpu_info_, -1, 0);
1758  EXPECT_EQ(0, max_diff);
1759}
1760
1761TEST_F(LibYUVPlanarTest, ARGBSobelToPlane_Opt) {
1762  int max_diff = TestSobelToPlane(benchmark_width_, benchmark_height_,
1763                                  benchmark_iterations_, disable_cpu_flags_,
1764                                  benchmark_cpu_info_, +1, 0);
1765  EXPECT_EQ(0, max_diff);
1766}
1767
1768static int TestSobelXY(int width,
1769                       int height,
1770                       int benchmark_iterations,
1771                       int disable_cpu_flags,
1772                       int benchmark_cpu_info,
1773                       int invert,
1774                       int off) {
1775  if (width < 1) {
1776    width = 1;
1777  }
1778  const int kBpp = 4;
1779  const int kStride = width * kBpp;
1780  align_buffer_page_end(src_argb_a, kStride * height + off);
1781  align_buffer_page_end(dst_argb_c, kStride * height);
1782  align_buffer_page_end(dst_argb_opt, kStride * height);
1783  memset(src_argb_a, 0, kStride * height + off);
1784  for (int i = 0; i < kStride * height; ++i) {
1785    src_argb_a[i + off] = (fastrand() & 0xff);
1786  }
1787  memset(dst_argb_c, 0, kStride * height);
1788  memset(dst_argb_opt, 0, kStride * height);
1789
1790  MaskCpuFlags(disable_cpu_flags);
1791  ARGBSobelXY(src_argb_a + off, kStride, dst_argb_c, kStride, width,
1792              invert * height);
1793  MaskCpuFlags(benchmark_cpu_info);
1794  for (int i = 0; i < benchmark_iterations; ++i) {
1795    ARGBSobelXY(src_argb_a + off, kStride, dst_argb_opt, kStride, width,
1796                invert * height);
1797  }
1798  int max_diff = 0;
1799  for (int i = 0; i < kStride * height; ++i) {
1800    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1801                       static_cast<int>(dst_argb_opt[i]));
1802    if (abs_diff > max_diff) {
1803      max_diff = abs_diff;
1804    }
1805  }
1806  free_aligned_buffer_page_end(src_argb_a);
1807  free_aligned_buffer_page_end(dst_argb_c);
1808  free_aligned_buffer_page_end(dst_argb_opt);
1809  return max_diff;
1810}
1811
1812TEST_F(LibYUVPlanarTest, ARGBSobelXY_Any) {
1813  int max_diff = TestSobelXY(benchmark_width_ - 1, benchmark_height_,
1814                             benchmark_iterations_, disable_cpu_flags_,
1815                             benchmark_cpu_info_, +1, 0);
1816  EXPECT_EQ(0, max_diff);
1817}
1818
1819TEST_F(LibYUVPlanarTest, ARGBSobelXY_Unaligned) {
1820  int max_diff =
1821      TestSobelXY(benchmark_width_, benchmark_height_, benchmark_iterations_,
1822                  disable_cpu_flags_, benchmark_cpu_info_, +1, 1);
1823  EXPECT_EQ(0, max_diff);
1824}
1825
1826TEST_F(LibYUVPlanarTest, ARGBSobelXY_Invert) {
1827  int max_diff =
1828      TestSobelXY(benchmark_width_, benchmark_height_, benchmark_iterations_,
1829                  disable_cpu_flags_, benchmark_cpu_info_, -1, 0);
1830  EXPECT_EQ(0, max_diff);
1831}
1832
1833TEST_F(LibYUVPlanarTest, ARGBSobelXY_Opt) {
1834  int max_diff =
1835      TestSobelXY(benchmark_width_, benchmark_height_, benchmark_iterations_,
1836                  disable_cpu_flags_, benchmark_cpu_info_, +1, 0);
1837  EXPECT_EQ(0, max_diff);
1838}
1839
1840static int TestBlur(int width,
1841                    int height,
1842                    int benchmark_iterations,
1843                    int disable_cpu_flags,
1844                    int benchmark_cpu_info,
1845                    int invert,
1846                    int off,
1847                    int radius) {
1848  if (width < 1) {
1849    width = 1;
1850  }
1851  const int kBpp = 4;
1852  const int kStride = width * kBpp;
1853  align_buffer_page_end(src_argb_a, kStride * height + off);
1854  align_buffer_page_end(dst_cumsum, width * height * 16);
1855  align_buffer_page_end(dst_argb_c, kStride * height);
1856  align_buffer_page_end(dst_argb_opt, kStride * height);
1857  for (int i = 0; i < kStride * height; ++i) {
1858    src_argb_a[i + off] = (fastrand() & 0xff);
1859  }
1860  memset(dst_cumsum, 0, width * height * 16);
1861  memset(dst_argb_c, 0, kStride * height);
1862  memset(dst_argb_opt, 0, kStride * height);
1863
1864  MaskCpuFlags(disable_cpu_flags);
1865  ARGBBlur(src_argb_a + off, kStride, dst_argb_c, kStride,
1866           reinterpret_cast<int32*>(dst_cumsum), width * 4, width,
1867           invert * height, radius);
1868  MaskCpuFlags(benchmark_cpu_info);
1869  for (int i = 0; i < benchmark_iterations; ++i) {
1870    ARGBBlur(src_argb_a + off, kStride, dst_argb_opt, kStride,
1871             reinterpret_cast<int32*>(dst_cumsum), width * 4, width,
1872             invert * height, radius);
1873  }
1874  int max_diff = 0;
1875  for (int i = 0; i < kStride * height; ++i) {
1876    int abs_diff = abs(static_cast<int>(dst_argb_c[i]) -
1877                       static_cast<int>(dst_argb_opt[i]));
1878    if (abs_diff > max_diff) {
1879      max_diff = abs_diff;
1880    }
1881  }
1882  free_aligned_buffer_page_end(src_argb_a);
1883  free_aligned_buffer_page_end(dst_cumsum);
1884  free_aligned_buffer_page_end(dst_argb_c);
1885  free_aligned_buffer_page_end(dst_argb_opt);
1886  return max_diff;
1887}
1888
1889static const int kBlurSize = 55;
1890TEST_F(LibYUVPlanarTest, ARGBBlur_Any) {
1891  int max_diff =
1892      TestBlur(benchmark_width_ - 1, benchmark_height_, benchmark_iterations_,
1893               disable_cpu_flags_, benchmark_cpu_info_, +1, 0, kBlurSize);
1894  EXPECT_LE(max_diff, 1);
1895}
1896
1897TEST_F(LibYUVPlanarTest, ARGBBlur_Unaligned) {
1898  int max_diff =
1899      TestBlur(benchmark_width_, benchmark_height_, benchmark_iterations_,
1900               disable_cpu_flags_, benchmark_cpu_info_, +1, 1, kBlurSize);
1901  EXPECT_LE(max_diff, 1);
1902}
1903
1904TEST_F(LibYUVPlanarTest, ARGBBlur_Invert) {
1905  int max_diff =
1906      TestBlur(benchmark_width_, benchmark_height_, benchmark_iterations_,
1907               disable_cpu_flags_, benchmark_cpu_info_, -1, 0, kBlurSize);
1908  EXPECT_LE(max_diff, 1);
1909}
1910
1911TEST_F(LibYUVPlanarTest, ARGBBlur_Opt) {
1912  int max_diff =
1913      TestBlur(benchmark_width_, benchmark_height_, benchmark_iterations_,
1914               disable_cpu_flags_, benchmark_cpu_info_, +1, 0, kBlurSize);
1915  EXPECT_LE(max_diff, 1);
1916}
1917
1918static const int kBlurSmallSize = 5;
1919TEST_F(LibYUVPlanarTest, ARGBBlurSmall_Any) {
1920  int max_diff =
1921      TestBlur(benchmark_width_ - 1, benchmark_height_, benchmark_iterations_,
1922               disable_cpu_flags_, benchmark_cpu_info_, +1, 0, kBlurSmallSize);
1923  EXPECT_LE(max_diff, 1);
1924}
1925
1926TEST_F(LibYUVPlanarTest, ARGBBlurSmall_Unaligned) {
1927  int max_diff =
1928      TestBlur(benchmark_width_, benchmark_height_, benchmark_iterations_,
1929               disable_cpu_flags_, benchmark_cpu_info_, +1, 1, kBlurSmallSize);
1930  EXPECT_LE(max_diff, 1);
1931}
1932
1933TEST_F(LibYUVPlanarTest, ARGBBlurSmall_Invert) {
1934  int max_diff =
1935      TestBlur(benchmark_width_, benchmark_height_, benchmark_iterations_,
1936               disable_cpu_flags_, benchmark_cpu_info_, -1, 0, kBlurSmallSize);
1937  EXPECT_LE(max_diff, 1);
1938}
1939
1940TEST_F(LibYUVPlanarTest, ARGBBlurSmall_Opt) {
1941  int max_diff =
1942      TestBlur(benchmark_width_, benchmark_height_, benchmark_iterations_,
1943               disable_cpu_flags_, benchmark_cpu_info_, +1, 0, kBlurSmallSize);
1944  EXPECT_LE(max_diff, 1);
1945}
1946
1947TEST_F(LibYUVPlanarTest, TestARGBPolynomial) {
1948  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
1949  SIMD_ALIGNED(uint8 dst_pixels_opt[1280][4]);
1950  SIMD_ALIGNED(uint8 dst_pixels_c[1280][4]);
1951  memset(orig_pixels, 0, sizeof(orig_pixels));
1952
1953  SIMD_ALIGNED(static const float kWarmifyPolynomial[16]) = {
1954      0.94230f,  -3.03300f,    -2.92500f,    0.f,  // C0
1955      0.584500f, 1.112000f,    1.535000f,    1.f,  // C1 x
1956      0.001313f, -0.002503f,   -0.004496f,   0.f,  // C2 x * x
1957      0.0f,      0.000006965f, 0.000008781f, 0.f,  // C3 x * x * x
1958  };
1959
1960  // Test blue
1961  orig_pixels[0][0] = 255u;
1962  orig_pixels[0][1] = 0u;
1963  orig_pixels[0][2] = 0u;
1964  orig_pixels[0][3] = 128u;
1965  // Test green
1966  orig_pixels[1][0] = 0u;
1967  orig_pixels[1][1] = 255u;
1968  orig_pixels[1][2] = 0u;
1969  orig_pixels[1][3] = 0u;
1970  // Test red
1971  orig_pixels[2][0] = 0u;
1972  orig_pixels[2][1] = 0u;
1973  orig_pixels[2][2] = 255u;
1974  orig_pixels[2][3] = 255u;
1975  // Test white
1976  orig_pixels[3][0] = 255u;
1977  orig_pixels[3][1] = 255u;
1978  orig_pixels[3][2] = 255u;
1979  orig_pixels[3][3] = 255u;
1980  // Test color
1981  orig_pixels[4][0] = 16u;
1982  orig_pixels[4][1] = 64u;
1983  orig_pixels[4][2] = 192u;
1984  orig_pixels[4][3] = 224u;
1985  // Do 16 to test asm version.
1986  ARGBPolynomial(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
1987                 &kWarmifyPolynomial[0], 16, 1);
1988  EXPECT_EQ(235u, dst_pixels_opt[0][0]);
1989  EXPECT_EQ(0u, dst_pixels_opt[0][1]);
1990  EXPECT_EQ(0u, dst_pixels_opt[0][2]);
1991  EXPECT_EQ(128u, dst_pixels_opt[0][3]);
1992  EXPECT_EQ(0u, dst_pixels_opt[1][0]);
1993  EXPECT_EQ(233u, dst_pixels_opt[1][1]);
1994  EXPECT_EQ(0u, dst_pixels_opt[1][2]);
1995  EXPECT_EQ(0u, dst_pixels_opt[1][3]);
1996  EXPECT_EQ(0u, dst_pixels_opt[2][0]);
1997  EXPECT_EQ(0u, dst_pixels_opt[2][1]);
1998  EXPECT_EQ(241u, dst_pixels_opt[2][2]);
1999  EXPECT_EQ(255u, dst_pixels_opt[2][3]);
2000  EXPECT_EQ(235u, dst_pixels_opt[3][0]);
2001  EXPECT_EQ(233u, dst_pixels_opt[3][1]);
2002  EXPECT_EQ(241u, dst_pixels_opt[3][2]);
2003  EXPECT_EQ(255u, dst_pixels_opt[3][3]);
2004  EXPECT_EQ(10u, dst_pixels_opt[4][0]);
2005  EXPECT_EQ(59u, dst_pixels_opt[4][1]);
2006  EXPECT_EQ(188u, dst_pixels_opt[4][2]);
2007  EXPECT_EQ(224u, dst_pixels_opt[4][3]);
2008
2009  for (int i = 0; i < 1280; ++i) {
2010    orig_pixels[i][0] = i;
2011    orig_pixels[i][1] = i / 2;
2012    orig_pixels[i][2] = i / 3;
2013    orig_pixels[i][3] = i;
2014  }
2015
2016  MaskCpuFlags(disable_cpu_flags_);
2017  ARGBPolynomial(&orig_pixels[0][0], 0, &dst_pixels_c[0][0], 0,
2018                 &kWarmifyPolynomial[0], 1280, 1);
2019  MaskCpuFlags(benchmark_cpu_info_);
2020
2021  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
2022    ARGBPolynomial(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
2023                   &kWarmifyPolynomial[0], 1280, 1);
2024  }
2025
2026  for (int i = 0; i < 1280; ++i) {
2027    EXPECT_EQ(dst_pixels_c[i][0], dst_pixels_opt[i][0]);
2028    EXPECT_EQ(dst_pixels_c[i][1], dst_pixels_opt[i][1]);
2029    EXPECT_EQ(dst_pixels_c[i][2], dst_pixels_opt[i][2]);
2030    EXPECT_EQ(dst_pixels_c[i][3], dst_pixels_opt[i][3]);
2031  }
2032}
2033
2034int TestHalfFloatPlane(int benchmark_width,
2035                       int benchmark_height,
2036                       int benchmark_iterations,
2037                       int disable_cpu_flags,
2038                       int benchmark_cpu_info,
2039                       float scale,
2040                       int mask) {
2041  int i, j;
2042  const int y_plane_size = benchmark_width * benchmark_height * 2;
2043
2044  align_buffer_page_end(orig_y, y_plane_size * 3);
2045  uint8* dst_opt = orig_y + y_plane_size;
2046  uint8* dst_c = orig_y + y_plane_size * 2;
2047
2048  MemRandomize(orig_y, y_plane_size);
2049  memset(dst_c, 0, y_plane_size);
2050  memset(dst_opt, 1, y_plane_size);
2051
2052  for (i = 0; i < y_plane_size / 2; ++i) {
2053    reinterpret_cast<uint16*>(orig_y)[i] &= mask;
2054  }
2055
2056  // Disable all optimizations.
2057  MaskCpuFlags(disable_cpu_flags);
2058  for (j = 0; j < benchmark_iterations; j++) {
2059    HalfFloatPlane(reinterpret_cast<uint16*>(orig_y), benchmark_width * 2,
2060                   reinterpret_cast<uint16*>(dst_c), benchmark_width * 2, scale,
2061                   benchmark_width, benchmark_height);
2062  }
2063
2064  // Enable optimizations.
2065  MaskCpuFlags(benchmark_cpu_info);
2066  for (j = 0; j < benchmark_iterations; j++) {
2067    HalfFloatPlane(reinterpret_cast<uint16*>(orig_y), benchmark_width * 2,
2068                   reinterpret_cast<uint16*>(dst_opt), benchmark_width * 2,
2069                   scale, benchmark_width, benchmark_height);
2070  }
2071
2072  int max_diff = 0;
2073  for (i = 0; i < y_plane_size / 2; ++i) {
2074    int abs_diff = abs(static_cast<int>(reinterpret_cast<uint16*>(dst_c)[i]) -
2075                       static_cast<int>(reinterpret_cast<uint16*>(dst_opt)[i]));
2076    if (abs_diff > max_diff) {
2077      max_diff = abs_diff;
2078    }
2079  }
2080
2081  free_aligned_buffer_page_end(orig_y);
2082  return max_diff;
2083}
2084
2085#if defined(__arm__)
2086static void EnableFlushDenormalToZero(void) {
2087  uint32_t cw;
2088  __asm__ __volatile__(
2089      "vmrs   %0, fpscr         \n"
2090      "orr    %0, %0, #0x1000000        \n"
2091      "vmsr   fpscr, %0         \n"
2092      : "=r"(cw)::"memory");
2093}
2094#endif
2095
2096// 5 bit exponent with bias of 15 will underflow to a denormal if scale causes
2097// exponent to be less than 0.  15 - log2(65536) = -1/  This shouldnt normally
2098// happen since scale is 1/(1<<bits) where bits is 9, 10 or 12.
2099
2100TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_16bit_denormal) {
2101// 32 bit arm rounding on denormal case is off by 1 compared to C.
2102#if defined(__arm__)
2103  EnableFlushDenormalToZero();
2104#endif
2105  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2106                                benchmark_iterations_, disable_cpu_flags_,
2107                                benchmark_cpu_info_, 1.0f / 65536.0f, 65535);
2108  EXPECT_EQ(0, diff);
2109}
2110
2111TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_16bit_One) {
2112  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2113                                benchmark_iterations_, disable_cpu_flags_,
2114                                benchmark_cpu_info_, 1.0f, 65535);
2115  EXPECT_LE(diff, 1);
2116}
2117
2118TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_16bit_Opt) {
2119  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2120                                benchmark_iterations_, disable_cpu_flags_,
2121                                benchmark_cpu_info_, 1.0f / 4096.0f, 65535);
2122  EXPECT_EQ(0, diff);
2123}
2124
2125TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_10bit_Opt) {
2126  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2127                                benchmark_iterations_, disable_cpu_flags_,
2128                                benchmark_cpu_info_, 1.0f / 1024.0f, 1023);
2129  EXPECT_EQ(0, diff);
2130}
2131
2132TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_9bit_Opt) {
2133  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2134                                benchmark_iterations_, disable_cpu_flags_,
2135                                benchmark_cpu_info_, 1.0f / 512.0f, 511);
2136  EXPECT_EQ(0, diff);
2137}
2138
2139TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_Opt) {
2140  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2141                                benchmark_iterations_, disable_cpu_flags_,
2142                                benchmark_cpu_info_, 1.0f / 4096.0f, 4095);
2143  EXPECT_EQ(0, diff);
2144}
2145
2146TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_Offby1) {
2147  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2148                                benchmark_iterations_, disable_cpu_flags_,
2149                                benchmark_cpu_info_, 1.0f / 4095.0f, 4095);
2150  EXPECT_EQ(0, diff);
2151}
2152
2153TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_One) {
2154  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2155                                benchmark_iterations_, disable_cpu_flags_,
2156                                benchmark_cpu_info_, 1.0f, 2047);
2157  EXPECT_EQ(0, diff);
2158}
2159
2160TEST_F(LibYUVPlanarTest, TestHalfFloatPlane_12bit_One) {
2161  int diff = TestHalfFloatPlane(benchmark_width_, benchmark_height_,
2162                                benchmark_iterations_, disable_cpu_flags_,
2163                                benchmark_cpu_info_, 1.0f, 4095);
2164  EXPECT_LE(diff, 1);
2165}
2166
2167TEST_F(LibYUVPlanarTest, TestARGBLumaColorTable) {
2168  SIMD_ALIGNED(uint8 orig_pixels[1280][4]);
2169  SIMD_ALIGNED(uint8 dst_pixels_opt[1280][4]);
2170  SIMD_ALIGNED(uint8 dst_pixels_c[1280][4]);
2171  memset(orig_pixels, 0, sizeof(orig_pixels));
2172
2173  align_buffer_page_end(lumacolortable, 32768);
2174  int v = 0;
2175  for (int i = 0; i < 32768; ++i) {
2176    lumacolortable[i] = v;
2177    v += 3;
2178  }
2179  // Test blue
2180  orig_pixels[0][0] = 255u;
2181  orig_pixels[0][1] = 0u;
2182  orig_pixels[0][2] = 0u;
2183  orig_pixels[0][3] = 128u;
2184  // Test green
2185  orig_pixels[1][0] = 0u;
2186  orig_pixels[1][1] = 255u;
2187  orig_pixels[1][2] = 0u;
2188  orig_pixels[1][3] = 0u;
2189  // Test red
2190  orig_pixels[2][0] = 0u;
2191  orig_pixels[2][1] = 0u;
2192  orig_pixels[2][2] = 255u;
2193  orig_pixels[2][3] = 255u;
2194  // Test color
2195  orig_pixels[3][0] = 16u;
2196  orig_pixels[3][1] = 64u;
2197  orig_pixels[3][2] = 192u;
2198  orig_pixels[3][3] = 224u;
2199  // Do 16 to test asm version.
2200  ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
2201                     &lumacolortable[0], 16, 1);
2202  EXPECT_EQ(253u, dst_pixels_opt[0][0]);
2203  EXPECT_EQ(0u, dst_pixels_opt[0][1]);
2204  EXPECT_EQ(0u, dst_pixels_opt[0][2]);
2205  EXPECT_EQ(128u, dst_pixels_opt[0][3]);
2206  EXPECT_EQ(0u, dst_pixels_opt[1][0]);
2207  EXPECT_EQ(253u, dst_pixels_opt[1][1]);
2208  EXPECT_EQ(0u, dst_pixels_opt[1][2]);
2209  EXPECT_EQ(0u, dst_pixels_opt[1][3]);
2210  EXPECT_EQ(0u, dst_pixels_opt[2][0]);
2211  EXPECT_EQ(0u, dst_pixels_opt[2][1]);
2212  EXPECT_EQ(253u, dst_pixels_opt[2][2]);
2213  EXPECT_EQ(255u, dst_pixels_opt[2][3]);
2214  EXPECT_EQ(48u, dst_pixels_opt[3][0]);
2215  EXPECT_EQ(192u, dst_pixels_opt[3][1]);
2216  EXPECT_EQ(64u, dst_pixels_opt[3][2]);
2217  EXPECT_EQ(224u, dst_pixels_opt[3][3]);
2218
2219  for (int i = 0; i < 1280; ++i) {
2220    orig_pixels[i][0] = i;
2221    orig_pixels[i][1] = i / 2;
2222    orig_pixels[i][2] = i / 3;
2223    orig_pixels[i][3] = i;
2224  }
2225
2226  MaskCpuFlags(disable_cpu_flags_);
2227  ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels_c[0][0], 0,
2228                     lumacolortable, 1280, 1);
2229  MaskCpuFlags(benchmark_cpu_info_);
2230
2231  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
2232    ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels_opt[0][0], 0,
2233                       lumacolortable, 1280, 1);
2234  }
2235  for (int i = 0; i < 1280; ++i) {
2236    EXPECT_EQ(dst_pixels_c[i][0], dst_pixels_opt[i][0]);
2237    EXPECT_EQ(dst_pixels_c[i][1], dst_pixels_opt[i][1]);
2238    EXPECT_EQ(dst_pixels_c[i][2], dst_pixels_opt[i][2]);
2239    EXPECT_EQ(dst_pixels_c[i][3], dst_pixels_opt[i][3]);
2240  }
2241
2242  free_aligned_buffer_page_end(lumacolortable);
2243}
2244
2245TEST_F(LibYUVPlanarTest, TestARGBCopyAlpha) {
2246  const int kSize = benchmark_width_ * benchmark_height_ * 4;
2247  align_buffer_page_end(orig_pixels, kSize);
2248  align_buffer_page_end(dst_pixels_opt, kSize);
2249  align_buffer_page_end(dst_pixels_c, kSize);
2250
2251  MemRandomize(orig_pixels, kSize);
2252  MemRandomize(dst_pixels_opt, kSize);
2253  memcpy(dst_pixels_c, dst_pixels_opt, kSize);
2254
2255  MaskCpuFlags(disable_cpu_flags_);
2256  ARGBCopyAlpha(orig_pixels, benchmark_width_ * 4, dst_pixels_c,
2257                benchmark_width_ * 4, benchmark_width_, benchmark_height_);
2258  MaskCpuFlags(benchmark_cpu_info_);
2259
2260  for (int i = 0; i < benchmark_iterations_; ++i) {
2261    ARGBCopyAlpha(orig_pixels, benchmark_width_ * 4, dst_pixels_opt,
2262                  benchmark_width_ * 4, benchmark_width_, benchmark_height_);
2263  }
2264  for (int i = 0; i < kSize; ++i) {
2265    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2266  }
2267
2268  free_aligned_buffer_page_end(dst_pixels_c);
2269  free_aligned_buffer_page_end(dst_pixels_opt);
2270  free_aligned_buffer_page_end(orig_pixels);
2271}
2272
2273TEST_F(LibYUVPlanarTest, TestARGBExtractAlpha) {
2274  const int kPixels = benchmark_width_ * benchmark_height_;
2275  align_buffer_page_end(src_pixels, kPixels * 4);
2276  align_buffer_page_end(dst_pixels_opt, kPixels);
2277  align_buffer_page_end(dst_pixels_c, kPixels);
2278
2279  MemRandomize(src_pixels, kPixels * 4);
2280  MemRandomize(dst_pixels_opt, kPixels);
2281  memcpy(dst_pixels_c, dst_pixels_opt, kPixels);
2282
2283  MaskCpuFlags(disable_cpu_flags_);
2284  ARGBExtractAlpha(src_pixels, benchmark_width_ * 4, dst_pixels_c,
2285                   benchmark_width_, benchmark_width_, benchmark_height_);
2286  MaskCpuFlags(benchmark_cpu_info_);
2287
2288  for (int i = 0; i < benchmark_iterations_; ++i) {
2289    ARGBExtractAlpha(src_pixels, benchmark_width_ * 4, dst_pixels_opt,
2290                     benchmark_width_, benchmark_width_, benchmark_height_);
2291  }
2292  for (int i = 0; i < kPixels; ++i) {
2293    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2294  }
2295
2296  free_aligned_buffer_page_end(dst_pixels_c);
2297  free_aligned_buffer_page_end(dst_pixels_opt);
2298  free_aligned_buffer_page_end(src_pixels);
2299}
2300
2301TEST_F(LibYUVPlanarTest, TestARGBCopyYToAlpha) {
2302  const int kPixels = benchmark_width_ * benchmark_height_;
2303  align_buffer_page_end(orig_pixels, kPixels);
2304  align_buffer_page_end(dst_pixels_opt, kPixels * 4);
2305  align_buffer_page_end(dst_pixels_c, kPixels * 4);
2306
2307  MemRandomize(orig_pixels, kPixels);
2308  MemRandomize(dst_pixels_opt, kPixels * 4);
2309  memcpy(dst_pixels_c, dst_pixels_opt, kPixels * 4);
2310
2311  MaskCpuFlags(disable_cpu_flags_);
2312  ARGBCopyYToAlpha(orig_pixels, benchmark_width_, dst_pixels_c,
2313                   benchmark_width_ * 4, benchmark_width_, benchmark_height_);
2314  MaskCpuFlags(benchmark_cpu_info_);
2315
2316  for (int i = 0; i < benchmark_iterations_; ++i) {
2317    ARGBCopyYToAlpha(orig_pixels, benchmark_width_, dst_pixels_opt,
2318                     benchmark_width_ * 4, benchmark_width_, benchmark_height_);
2319  }
2320  for (int i = 0; i < kPixels * 4; ++i) {
2321    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2322  }
2323
2324  free_aligned_buffer_page_end(dst_pixels_c);
2325  free_aligned_buffer_page_end(dst_pixels_opt);
2326  free_aligned_buffer_page_end(orig_pixels);
2327}
2328
2329static int TestARGBRect(int width,
2330                        int height,
2331                        int benchmark_iterations,
2332                        int disable_cpu_flags,
2333                        int benchmark_cpu_info,
2334                        int invert,
2335                        int off,
2336                        int bpp) {
2337  if (width < 1) {
2338    width = 1;
2339  }
2340  const int kStride = width * bpp;
2341  const int kSize = kStride * height;
2342  const uint32 v32 = fastrand() & (bpp == 4 ? 0xffffffff : 0xff);
2343
2344  align_buffer_page_end(dst_argb_c, kSize + off);
2345  align_buffer_page_end(dst_argb_opt, kSize + off);
2346
2347  MemRandomize(dst_argb_c + off, kSize);
2348  memcpy(dst_argb_opt + off, dst_argb_c + off, kSize);
2349
2350  MaskCpuFlags(disable_cpu_flags);
2351  if (bpp == 4) {
2352    ARGBRect(dst_argb_c + off, kStride, 0, 0, width, invert * height, v32);
2353  } else {
2354    SetPlane(dst_argb_c + off, kStride, width, invert * height, v32);
2355  }
2356
2357  MaskCpuFlags(benchmark_cpu_info);
2358  for (int i = 0; i < benchmark_iterations; ++i) {
2359    if (bpp == 4) {
2360      ARGBRect(dst_argb_opt + off, kStride, 0, 0, width, invert * height, v32);
2361    } else {
2362      SetPlane(dst_argb_opt + off, kStride, width, invert * height, v32);
2363    }
2364  }
2365  int max_diff = 0;
2366  for (int i = 0; i < kStride * height; ++i) {
2367    int abs_diff = abs(static_cast<int>(dst_argb_c[i + off]) -
2368                       static_cast<int>(dst_argb_opt[i + off]));
2369    if (abs_diff > max_diff) {
2370      max_diff = abs_diff;
2371    }
2372  }
2373  free_aligned_buffer_page_end(dst_argb_c);
2374  free_aligned_buffer_page_end(dst_argb_opt);
2375  return max_diff;
2376}
2377
2378TEST_F(LibYUVPlanarTest, ARGBRect_Any) {
2379  int max_diff = TestARGBRect(benchmark_width_ - 1, benchmark_height_,
2380                              benchmark_iterations_, disable_cpu_flags_,
2381                              benchmark_cpu_info_, +1, 0, 4);
2382  EXPECT_EQ(0, max_diff);
2383}
2384
2385TEST_F(LibYUVPlanarTest, ARGBRect_Unaligned) {
2386  int max_diff =
2387      TestARGBRect(benchmark_width_, benchmark_height_, benchmark_iterations_,
2388                   disable_cpu_flags_, benchmark_cpu_info_, +1, 1, 4);
2389  EXPECT_EQ(0, max_diff);
2390}
2391
2392TEST_F(LibYUVPlanarTest, ARGBRect_Invert) {
2393  int max_diff =
2394      TestARGBRect(benchmark_width_, benchmark_height_, benchmark_iterations_,
2395                   disable_cpu_flags_, benchmark_cpu_info_, -1, 0, 4);
2396  EXPECT_EQ(0, max_diff);
2397}
2398
2399TEST_F(LibYUVPlanarTest, ARGBRect_Opt) {
2400  int max_diff =
2401      TestARGBRect(benchmark_width_, benchmark_height_, benchmark_iterations_,
2402                   disable_cpu_flags_, benchmark_cpu_info_, +1, 0, 4);
2403  EXPECT_EQ(0, max_diff);
2404}
2405
2406TEST_F(LibYUVPlanarTest, SetPlane_Any) {
2407  int max_diff = TestARGBRect(benchmark_width_ - 1, benchmark_height_,
2408                              benchmark_iterations_, disable_cpu_flags_,
2409                              benchmark_cpu_info_, +1, 0, 1);
2410  EXPECT_EQ(0, max_diff);
2411}
2412
2413TEST_F(LibYUVPlanarTest, SetPlane_Unaligned) {
2414  int max_diff =
2415      TestARGBRect(benchmark_width_, benchmark_height_, benchmark_iterations_,
2416                   disable_cpu_flags_, benchmark_cpu_info_, +1, 1, 1);
2417  EXPECT_EQ(0, max_diff);
2418}
2419
2420TEST_F(LibYUVPlanarTest, SetPlane_Invert) {
2421  int max_diff =
2422      TestARGBRect(benchmark_width_, benchmark_height_, benchmark_iterations_,
2423                   disable_cpu_flags_, benchmark_cpu_info_, -1, 0, 1);
2424  EXPECT_EQ(0, max_diff);
2425}
2426
2427TEST_F(LibYUVPlanarTest, SetPlane_Opt) {
2428  int max_diff =
2429      TestARGBRect(benchmark_width_, benchmark_height_, benchmark_iterations_,
2430                   disable_cpu_flags_, benchmark_cpu_info_, +1, 0, 1);
2431  EXPECT_EQ(0, max_diff);
2432}
2433
2434TEST_F(LibYUVPlanarTest, MergeUVPlane_Opt) {
2435  const int kPixels = benchmark_width_ * benchmark_height_;
2436  align_buffer_page_end(src_pixels, kPixels * 2);
2437  align_buffer_page_end(tmp_pixels_u, kPixels);
2438  align_buffer_page_end(tmp_pixels_v, kPixels);
2439  align_buffer_page_end(dst_pixels_opt, kPixels * 2);
2440  align_buffer_page_end(dst_pixels_c, kPixels * 2);
2441
2442  MemRandomize(src_pixels, kPixels * 2);
2443  MemRandomize(tmp_pixels_u, kPixels);
2444  MemRandomize(tmp_pixels_v, kPixels);
2445  MemRandomize(dst_pixels_opt, kPixels * 2);
2446  MemRandomize(dst_pixels_c, kPixels * 2);
2447
2448  MaskCpuFlags(disable_cpu_flags_);
2449  SplitUVPlane(src_pixels, benchmark_width_ * 2, tmp_pixels_u, benchmark_width_,
2450               tmp_pixels_v, benchmark_width_, benchmark_width_,
2451               benchmark_height_);
2452  MergeUVPlane(tmp_pixels_u, benchmark_width_, tmp_pixels_v, benchmark_width_,
2453               dst_pixels_c, benchmark_width_ * 2, benchmark_width_,
2454               benchmark_height_);
2455  MaskCpuFlags(benchmark_cpu_info_);
2456
2457  SplitUVPlane(src_pixels, benchmark_width_ * 2, tmp_pixels_u, benchmark_width_,
2458               tmp_pixels_v, benchmark_width_, benchmark_width_,
2459               benchmark_height_);
2460
2461  for (int i = 0; i < benchmark_iterations_; ++i) {
2462    MergeUVPlane(tmp_pixels_u, benchmark_width_, tmp_pixels_v, benchmark_width_,
2463                 dst_pixels_opt, benchmark_width_ * 2, benchmark_width_,
2464                 benchmark_height_);
2465  }
2466
2467  for (int i = 0; i < kPixels * 2; ++i) {
2468    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2469  }
2470
2471  free_aligned_buffer_page_end(src_pixels);
2472  free_aligned_buffer_page_end(tmp_pixels_u);
2473  free_aligned_buffer_page_end(tmp_pixels_v);
2474  free_aligned_buffer_page_end(dst_pixels_opt);
2475  free_aligned_buffer_page_end(dst_pixels_c);
2476}
2477
2478TEST_F(LibYUVPlanarTest, SplitUVPlane_Opt) {
2479  const int kPixels = benchmark_width_ * benchmark_height_;
2480  align_buffer_page_end(src_pixels, kPixels * 2);
2481  align_buffer_page_end(tmp_pixels_u, kPixels);
2482  align_buffer_page_end(tmp_pixels_v, kPixels);
2483  align_buffer_page_end(dst_pixels_opt, kPixels * 2);
2484  align_buffer_page_end(dst_pixels_c, kPixels * 2);
2485
2486  MemRandomize(src_pixels, kPixels * 2);
2487  MemRandomize(tmp_pixels_u, kPixels);
2488  MemRandomize(tmp_pixels_v, kPixels);
2489  MemRandomize(dst_pixels_opt, kPixels * 2);
2490  MemRandomize(dst_pixels_c, kPixels * 2);
2491
2492  MaskCpuFlags(disable_cpu_flags_);
2493  SplitUVPlane(src_pixels, benchmark_width_ * 2, tmp_pixels_u, benchmark_width_,
2494               tmp_pixels_v, benchmark_width_, benchmark_width_,
2495               benchmark_height_);
2496  MergeUVPlane(tmp_pixels_u, benchmark_width_, tmp_pixels_v, benchmark_width_,
2497               dst_pixels_c, benchmark_width_ * 2, benchmark_width_,
2498               benchmark_height_);
2499  MaskCpuFlags(benchmark_cpu_info_);
2500
2501  for (int i = 0; i < benchmark_iterations_; ++i) {
2502    SplitUVPlane(src_pixels, benchmark_width_ * 2, tmp_pixels_u,
2503                 benchmark_width_, tmp_pixels_v, benchmark_width_,
2504                 benchmark_width_, benchmark_height_);
2505  }
2506  MergeUVPlane(tmp_pixels_u, benchmark_width_, tmp_pixels_v, benchmark_width_,
2507               dst_pixels_opt, benchmark_width_ * 2, benchmark_width_,
2508               benchmark_height_);
2509
2510  for (int i = 0; i < kPixels * 2; ++i) {
2511    EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
2512  }
2513
2514  free_aligned_buffer_page_end(src_pixels);
2515  free_aligned_buffer_page_end(tmp_pixels_u);
2516  free_aligned_buffer_page_end(tmp_pixels_v);
2517  free_aligned_buffer_page_end(dst_pixels_opt);
2518  free_aligned_buffer_page_end(dst_pixels_c);
2519}
2520
2521}  // namespace libyuv
2522