188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org/*
288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *
488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *  Use of this source code is governed by a BSD-style license
588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *  that can be found in the LICENSE file in the root of the source
688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *  tree. An additional intellectual property rights grant can be found
788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *  in the file PATENTS. All contributing project authors may
888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org *  be found in the AUTHORS file in the root of the source tree.
988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org */
1088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
1141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/planar_functions.h"
1288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
1388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#include <string.h>  // for memset()
1488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
1541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/cpu_id.h"
1688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#ifdef HAVE_JPEG
1741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/mjpeg_decoder.h"
1888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
1941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/row.h"
2088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
2188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#ifdef __cplusplus
2288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgnamespace libyuv {
2388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgextern "C" {
2488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
2588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
2688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Copy a plane of data
2788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
2888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid CopyPlane(const uint8* src_y, int src_stride_y,
2988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
3088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
3188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
3288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
3388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
3488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_y == width &&
3588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_y == width) {
3688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
3788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
3888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = dst_stride_y = 0;
3988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
4041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // Nothing to do.
4141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  if (src_y == dst_y && src_stride_y == dst_stride_y) {
4241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    return;
4341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  }
4488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_X86)
4588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
4688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_X86;
4788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
4888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
4988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_SSE2)
5088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
5188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
5288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
5388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_SSE2;
5488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
5588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
5688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_ERMS)
5788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasERMS)) {
5888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_ERMS;
5988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
6088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
6188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_NEON)
6288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
6388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_NEON;
6488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
6588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
6688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_MIPS)
6788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS)) {
6888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_MIPS;
6988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
7088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
7188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
7288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Copy plane
7388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
7488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow(src_y, dst_y, width);
7588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
7688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_y += dst_stride_y;
7788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
7888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
7988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
8088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
8188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid CopyPlane_16(const uint16* src_y, int src_stride_y,
8288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  uint16* dst_y, int dst_stride_y,
8388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  int width, int height) {
8488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
8588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*CopyRow)(const uint16* src, uint16* dst, int width) = CopyRow_16_C;
8688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
8788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_y == width &&
8888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_y == width) {
8988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
9088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
9188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = dst_stride_y = 0;
9288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
9388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_16_X86)
9488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
9588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_16_X86;
9688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
9788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
9888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_16_SSE2)
9988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
10088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
10188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
10288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_16_SSE2;
10388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
10488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
10588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_16_ERMS)
10688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasERMS)) {
10788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_16_ERMS;
10888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
10988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
11088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_16_NEON)
11188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
11288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_16_NEON;
11388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
11488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
11588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_COPYROW_16_MIPS)
11688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS)) {
11788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow = CopyRow_16_MIPS;
11888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
11988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
12088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
12188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Copy plane
12288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
12388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyRow(src_y, dst_y, width);
12488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
12588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_y += dst_stride_y;
12688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
12788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
12888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
12988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Copy I422.
13088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
13188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I422Copy(const uint8* src_y, int src_stride_y,
13288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             const uint8* src_u, int src_stride_u,
13388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             const uint8* src_v, int src_stride_v,
13488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_y, int dst_stride_y,
13588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_u, int dst_stride_u,
13688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_v, int dst_stride_v,
13788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int width, int height) {
13888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int halfwidth = (width + 1) >> 1;
13988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v ||
14088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_y || !dst_u || !dst_v ||
14188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
14288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
14388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
14488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
14588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
14688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
14788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
14888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_u = src_u + (height - 1) * src_stride_u;
14988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_v = src_v + (height - 1) * src_stride_v;
15088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
15188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_u = -src_stride_u;
15288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_v = -src_stride_v;
15388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
15488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
15588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
15688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
15788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
15888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
15988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
16088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Copy I444.
16188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
16288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I444Copy(const uint8* src_y, int src_stride_y,
16388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             const uint8* src_u, int src_stride_u,
16488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             const uint8* src_v, int src_stride_v,
16588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_y, int dst_stride_y,
16688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_u, int dst_stride_u,
16788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_v, int dst_stride_v,
16888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int width, int height) {
16988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v ||
17088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_y || !dst_u || !dst_v ||
17188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
17288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
17388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
17488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
17588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
17688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
17788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
17888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_u = src_u + (height - 1) * src_stride_u;
17988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_v = src_v + (height - 1) * src_stride_v;
18088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
18188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_u = -src_stride_u;
18288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_v = -src_stride_v;
18388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
18488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
18588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
18688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
18788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
18888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
18988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
19088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
19188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Copy I400.
19288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
19388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I400ToI400(const uint8* src_y, int src_stride_y,
19488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
19588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
19688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !dst_y || width <= 0 || height == 0) {
19788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
19888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
19988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
20088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
20188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
20288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
20388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
20488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
20588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
20688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
20788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
20888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
20988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert I420 to I400.
21088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
21188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I420ToI400(const uint8* src_y, int src_stride_y,
21288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_u, int src_stride_u,
21388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_v, int src_stride_v,
21488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
21588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
21688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !dst_y || width <= 0 || height == 0) {
21788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
21888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
21988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
22088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
22188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
22288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
22388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
22488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
22588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
22688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
22788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
22888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
22988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Mirror a plane of data.
23088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid MirrorPlane(const uint8* src_y, int src_stride_y,
23188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint8* dst_y, int dst_stride_y,
23288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int width, int height) {
23388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
23488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*MirrorRow)(const uint8* src, uint8* dst, int width) = MirrorRow_C;
23588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
23688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
23788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
23888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
23988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
24088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
24188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_MIRRORROW_NEON)
24288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
24388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    MirrorRow = MirrorRow_NEON;
24488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
24588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
24688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_MIRRORROW_SSE2)
24788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) {
24888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    MirrorRow = MirrorRow_SSE2;
24988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
25088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
25188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_MIRRORROW_SSSE3)
25288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16) &&
25388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
25488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
25588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    MirrorRow = MirrorRow_SSSE3;
25688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
25788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
25888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_MIRRORROW_AVX2)
25988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 32)) {
26088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    MirrorRow = MirrorRow_AVX2;
26188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
26288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
26388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
26488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Mirror plane
26588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
26688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    MirrorRow(src_y, dst_y, width);
26788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
26888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_y += dst_stride_y;
26988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
27088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
27188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
27288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert YUY2 to I422.
27388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
27488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2,
27588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
27688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_u, int dst_stride_u,
27788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_v, int dst_stride_v,
27888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
27988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
28088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*YUY2ToUV422Row)(const uint8* src_yuy2,
28188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         uint8* dst_u, uint8* dst_v, int pix) =
28288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToUV422Row_C;
28388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) =
28488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToYRow_C;
28588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
28688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
28788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
28888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
28988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_yuy2 = -src_stride_yuy2;
29088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
29188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
29288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_yuy2 == width * 2 &&
29388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_y == width &&
29488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_u * 2 == width &&
29588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_v * 2 == width) {
29688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
29788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
29888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_yuy2 = dst_stride_y = dst_stride_u = dst_stride_v = 0;
29988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
30088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_YUY2TOYROW_SSE2)
30188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
30288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2;
30388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToYRow = YUY2ToYRow_Any_SSE2;
30488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
30588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2;
30688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2;
30788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) {
30888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        YUY2ToUV422Row = YUY2ToUV422Row_SSE2;
30988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
31088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          YUY2ToYRow = YUY2ToYRow_SSE2;
31188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        }
31288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
31388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
31488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
31588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
31688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_YUY2TOYROW_AVX2)
31788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
31888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2;
31988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToYRow = YUY2ToYRow_Any_AVX2;
32088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 32)) {
32188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToUV422Row = YUY2ToUV422Row_AVX2;
32288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToYRow = YUY2ToYRow_AVX2;
32388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
32488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
32588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
32688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_YUY2TOYROW_NEON)
32788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
32888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToYRow = YUY2ToYRow_Any_NEON;
32988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (width >= 16) {
33088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON;
33188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
33288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
33388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToYRow = YUY2ToYRow_NEON;
33488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      YUY2ToUV422Row = YUY2ToUV422Row_NEON;
33588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
33688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
33788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
33888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
33988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
34088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
34188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    YUY2ToYRow(src_yuy2, dst_y, width);
34288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_yuy2 += src_stride_yuy2;
34388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_y += dst_stride_y;
34488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_u += dst_stride_u;
34588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_v += dst_stride_v;
34688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
34788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
34888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
34988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
35088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert UYVY to I422.
35188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
35288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy,
35388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
35488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_u, int dst_stride_u,
35588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_v, int dst_stride_v,
35688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
35788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
35888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*UYVYToUV422Row)(const uint8* src_uyvy,
35988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         uint8* dst_u, uint8* dst_v, int pix) =
36088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToUV422Row_C;
36188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*UYVYToYRow)(const uint8* src_uyvy,
36288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     uint8* dst_y, int pix) = UYVYToYRow_C;
36388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
36488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
36588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
36688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
36788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_uyvy = -src_stride_uyvy;
36888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
36988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
37088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_uyvy == width * 2 &&
37188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_y == width &&
37288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_u * 2 == width &&
37388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_v * 2 == width) {
37488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
37588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
37688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_uyvy = dst_stride_y = dst_stride_u = dst_stride_v = 0;
37788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
37888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_UYVYTOYROW_SSE2)
37988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
38088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToUV422Row = UYVYToUV422Row_Any_SSE2;
38188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToYRow = UYVYToYRow_Any_SSE2;
38288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
38388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToUV422Row = UYVYToUV422Row_Unaligned_SSE2;
38488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToYRow = UYVYToYRow_Unaligned_SSE2;
38588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) {
38688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        UYVYToUV422Row = UYVYToUV422Row_SSE2;
38788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
38888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          UYVYToYRow = UYVYToYRow_SSE2;
38988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        }
39088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
39188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
39288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
39388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
39488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_UYVYTOYROW_AVX2)
39588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
39688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToUV422Row = UYVYToUV422Row_Any_AVX2;
39788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToYRow = UYVYToYRow_Any_AVX2;
39888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 32)) {
39988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToUV422Row = UYVYToUV422Row_AVX2;
40088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToYRow = UYVYToYRow_AVX2;
40188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
40288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
40388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
40488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_UYVYTOYROW_NEON)
40588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
40688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToYRow = UYVYToYRow_Any_NEON;
40788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (width >= 16) {
40888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToUV422Row = UYVYToUV422Row_Any_NEON;
40988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
41088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
41188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToYRow = UYVYToYRow_NEON;
41288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      UYVYToUV422Row = UYVYToUV422Row_NEON;
41388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
41488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
41588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
41688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
41788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
41888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToUV422Row(src_uyvy, dst_u, dst_v, width);
41988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    UYVYToYRow(src_uyvy, dst_y, width);
42088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_uyvy += src_stride_uyvy;
42188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_y += dst_stride_y;
42288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_u += dst_stride_u;
42388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_v += dst_stride_v;
42488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
42588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
42688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
42788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
42888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Mirror I400 with optional flipping
42988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
43088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I400Mirror(const uint8* src_y, int src_stride_y,
43188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
43288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
43388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !dst_y ||
43488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
43588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
43688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
43788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
43888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
43988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
44088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
44188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
44288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
44388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
44488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
44588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
44688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
44788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
44888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Mirror I420 with optional flipping
44988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
45088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I420Mirror(const uint8* src_y, int src_stride_y,
45188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_u, int src_stride_u,
45288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_v, int src_stride_v,
45388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_y, int dst_stride_y,
45488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_u, int dst_stride_u,
45588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_v, int dst_stride_v,
45688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
45788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int halfwidth = (width + 1) >> 1;
45888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int halfheight = (height + 1) >> 1;
45988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v || !dst_y || !dst_u || !dst_v ||
46088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
46188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
46288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
46388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
46488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
46588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
46688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    halfheight = (height + 1) >> 1;
46788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
46888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_u = src_u + (halfheight - 1) * src_stride_u;
46988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_v = src_v + (halfheight - 1) * src_stride_v;
47088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
47188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_u = -src_stride_u;
47288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_v = -src_stride_v;
47388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
47488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
47588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_y) {
47688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
47788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
47888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  MirrorPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
47988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  MirrorPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
48088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
48188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
48288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
48388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// ARGB mirror.
48488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
48588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBMirror(const uint8* src_argb, int src_stride_argb,
48688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_argb, int dst_stride_argb,
48788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
48888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
48988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) =
49088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBMirrorRow_C;
49188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
49288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
49388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
49488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
49588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
49688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
49788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
49888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
49988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
50088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
50188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBMIRRORROW_SSSE3)
50288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4) &&
50388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
50488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
50588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMirrorRow = ARGBMirrorRow_SSSE3;
50688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
50788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
50888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBMIRRORROW_AVX2)
50988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 8)) {
51088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMirrorRow = ARGBMirrorRow_AVX2;
51188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
51288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
51388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBMIRRORROW_NEON)
51488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 4)) {
51588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMirrorRow = ARGBMirrorRow_NEON;
51688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
51788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
51888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
51988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Mirror plane
52088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
52188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMirrorRow(src_argb, dst_argb, width);
52288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
52388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
52488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
52588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
52688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
52788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
52888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Get a blender that optimized for the CPU, alignment and pixel count.
52988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// As there are 6 blenders to choose from, the caller should try to use
53088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// the same blend function for all pixels if possible.
53188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
53288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgARGBBlendRow GetARGBBlend() {
53388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1,
53488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       uint8* dst_argb, int width) = ARGBBlendRow_C;
53588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBBLENDROW_SSSE3)
53688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3)) {
53788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBBlendRow = ARGBBlendRow_SSSE3;
53888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return ARGBBlendRow;
53988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
54088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
54188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBBLENDROW_SSE2)
54288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2)) {
54388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBBlendRow = ARGBBlendRow_SSE2;
54488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
54588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
54688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBBLENDROW_NEON)
54788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON)) {
54888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBBlendRow = ARGBBlendRow_NEON;
54988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
55088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
55188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return ARGBBlendRow;
55288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
55388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
55488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Alpha Blend 2 ARGB images and store to destination.
55588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
55688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBBlend(const uint8* src_argb0, int src_stride_argb0,
55788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              const uint8* src_argb1, int src_stride_argb1,
55888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint8* dst_argb, int dst_stride_argb,
55988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int width, int height) {
56088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
56188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1,
56288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       uint8* dst_argb, int width) = GetARGBBlend();
56388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
56488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
56588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
56688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
56788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
56888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
56988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
57088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = -dst_stride_argb;
57188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
57288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
57388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb0 == width * 4 &&
57488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_argb1 == width * 4 &&
57588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
57688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
57788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
57888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
57988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
58088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
58188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
58288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBBlendRow(src_argb0, src_argb1, dst_argb, width);
58388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb0 += src_stride_argb0;
58488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb1 += src_stride_argb1;
58588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
58688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
58788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
58888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
58988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
59088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Multiply 2 ARGB images and store to destination.
59188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
59288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBMultiply(const uint8* src_argb0, int src_stride_argb0,
59388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 const uint8* src_argb1, int src_stride_argb1,
59488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint8* dst_argb, int dst_stride_argb,
59588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int width, int height) {
59688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
59788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBMultiplyRow)(const uint8* src0, const uint8* src1, uint8* dst,
59888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int width) = ARGBMultiplyRow_C;
59988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
60088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
60188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
60288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
60388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
60488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
60588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
60688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = -dst_stride_argb;
60788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
60888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
60988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb0 == width * 4 &&
61088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_argb1 == width * 4 &&
61188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
61288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
61388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
61488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
61588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
61688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBMULTIPLYROW_SSE2)
61788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
61888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMultiplyRow = ARGBMultiplyRow_Any_SSE2;
61988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
62088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBMultiplyRow = ARGBMultiplyRow_SSE2;
62188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
62288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
62388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
62488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBMULTIPLYROW_AVX2)
62588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
62688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMultiplyRow = ARGBMultiplyRow_Any_AVX2;
62788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
62888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBMultiplyRow = ARGBMultiplyRow_AVX2;
62988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
63088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
63188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
63288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBMULTIPLYROW_NEON)
63388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
63488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMultiplyRow = ARGBMultiplyRow_Any_NEON;
63588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
63688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBMultiplyRow = ARGBMultiplyRow_NEON;
63788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
63888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
63988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
64088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
64188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Multiply plane
64288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
64388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBMultiplyRow(src_argb0, src_argb1, dst_argb, width);
64488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb0 += src_stride_argb0;
64588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb1 += src_stride_argb1;
64688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
64788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
64888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
64988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
65088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
65188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Add 2 ARGB images and store to destination.
65288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
65388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBAdd(const uint8* src_argb0, int src_stride_argb0,
65488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org            const uint8* src_argb1, int src_stride_argb1,
65588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org            uint8* dst_argb, int dst_stride_argb,
65688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org            int width, int height) {
65788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
65888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBAddRow)(const uint8* src0, const uint8* src1, uint8* dst,
65988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     int width) = ARGBAddRow_C;
66088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
66188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
66288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
66388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
66488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
66588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
66688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
66788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = -dst_stride_argb;
66888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
66988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
67088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb0 == width * 4 &&
67188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_argb1 == width * 4 &&
67288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
67388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
67488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
67588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
67688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
67788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBADDROW_SSE2) && defined(_MSC_VER)
67888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2)) {
67988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAddRow = ARGBAddRow_SSE2;
68088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
68188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
68288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBADDROW_SSE2) && !defined(_MSC_VER)
68388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
68488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAddRow = ARGBAddRow_Any_SSE2;
68588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
68688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAddRow = ARGBAddRow_SSE2;
68788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
68888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
68988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
69088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBADDROW_AVX2)
69188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
69288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAddRow = ARGBAddRow_Any_AVX2;
69388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
69488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAddRow = ARGBAddRow_AVX2;
69588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
69688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
69788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
69888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBADDROW_NEON)
69988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
70088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAddRow = ARGBAddRow_Any_NEON;
70188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
70288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAddRow = ARGBAddRow_NEON;
70388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
70488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
70588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
70688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
70788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Add plane
70888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
70988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAddRow(src_argb0, src_argb1, dst_argb, width);
71088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb0 += src_stride_argb0;
71188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb1 += src_stride_argb1;
71288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
71388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
71488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
71588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
71688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
71788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Subtract 2 ARGB images and store to destination.
71888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
71988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBSubtract(const uint8* src_argb0, int src_stride_argb0,
72088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 const uint8* src_argb1, int src_stride_argb1,
72188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint8* dst_argb, int dst_stride_argb,
72288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int width, int height) {
72388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
72488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBSubtractRow)(const uint8* src0, const uint8* src1, uint8* dst,
72588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int width) = ARGBSubtractRow_C;
72688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
72788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
72888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
72988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
73088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
73188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
73288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
73388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = -dst_stride_argb;
73488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
73588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
73688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb0 == width * 4 &&
73788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_argb1 == width * 4 &&
73888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
73988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
74088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
74188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
74288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
74388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSUBTRACTROW_SSE2)
74488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
74588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSubtractRow = ARGBSubtractRow_Any_SSE2;
74688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
74788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBSubtractRow = ARGBSubtractRow_SSE2;
74888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
74988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
75088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
75188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSUBTRACTROW_AVX2)
75288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
75388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSubtractRow = ARGBSubtractRow_Any_AVX2;
75488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
75588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBSubtractRow = ARGBSubtractRow_AVX2;
75688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
75788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
75888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
75988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSUBTRACTROW_NEON)
76088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
76188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSubtractRow = ARGBSubtractRow_Any_NEON;
76288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
76388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBSubtractRow = ARGBSubtractRow_NEON;
76488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
76588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
76688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
76788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
76888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Subtract plane
76988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
77088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSubtractRow(src_argb0, src_argb1, dst_argb, width);
77188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb0 += src_stride_argb0;
77288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb1 += src_stride_argb1;
77388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
77488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
77588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
77688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
77788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
77888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert I422 to BGRA.
77988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
78088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I422ToBGRA(const uint8* src_y, int src_stride_y,
78188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_u, int src_stride_u,
78288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_v, int src_stride_v,
78388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_bgra, int dst_stride_bgra,
78488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
78588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
78688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*I422ToBGRARow)(const uint8* y_buf,
78788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        const uint8* u_buf,
78888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        const uint8* v_buf,
78988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint8* rgb_buf,
79088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        int width) = I422ToBGRARow_C;
79188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v ||
79288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_bgra ||
79388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
79488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
79588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
79688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
79788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
79888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
79988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra;
80088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_bgra = -dst_stride_bgra;
80188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
80288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
80388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_y == width &&
80488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_u * 2 == width &&
80588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_v * 2 == width &&
80688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_bgra == width * 4) {
80788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
80888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
80988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = src_stride_u = src_stride_v = dst_stride_bgra = 0;
81088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
81188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_I422TOBGRAROW_NEON)
81288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON)) {
81388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToBGRARow = I422ToBGRARow_Any_NEON;
81488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
81588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      I422ToBGRARow = I422ToBGRARow_NEON;
81688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
81788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
81888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_I422TOBGRAROW_SSSE3)
81988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
82088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToBGRARow = I422ToBGRARow_Any_SSSE3;
82188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
82288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3;
82388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) {
82488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        I422ToBGRARow = I422ToBGRARow_SSSE3;
82588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
82688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
82788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
82888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2)
82988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
83088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
83188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
83288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
83388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) {
83488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2;
83588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
83688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
83788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
83888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
83988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width);
84088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_bgra += dst_stride_bgra;
84188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
84288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_u += src_stride_u;
84388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_v += src_stride_v;
84488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
84588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
84688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
84788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
84888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert I422 to ABGR.
84988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
85088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I422ToABGR(const uint8* src_y, int src_stride_y,
85188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_u, int src_stride_u,
85288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_v, int src_stride_v,
85388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_abgr, int dst_stride_abgr,
85488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
85588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
85688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*I422ToABGRRow)(const uint8* y_buf,
85788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        const uint8* u_buf,
85888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        const uint8* v_buf,
85988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint8* rgb_buf,
86088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        int width) = I422ToABGRRow_C;
86188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v ||
86288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_abgr ||
86388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
86488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
86588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
86688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
86788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
86888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
86988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr;
87088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_abgr = -dst_stride_abgr;
87188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
87288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
87388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_y == width &&
87488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_u * 2 == width &&
87588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_v * 2 == width &&
87688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_abgr == width * 4) {
87788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
87888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
87988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = src_stride_u = src_stride_v = dst_stride_abgr = 0;
88088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
88188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_I422TOABGRROW_NEON)
88288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON)) {
88388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToABGRRow = I422ToABGRRow_Any_NEON;
88488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
88588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      I422ToABGRRow = I422ToABGRRow_NEON;
88688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
88788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
88888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_I422TOABGRROW_SSSE3)
88988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
89088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToABGRRow = I422ToABGRRow_Any_SSSE3;
89188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
89288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3;
89388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) {
89488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        I422ToABGRRow = I422ToABGRRow_SSSE3;
89588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
89688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
89788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
89888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
89988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
90088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
90188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width);
90288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_abgr += dst_stride_abgr;
90388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
90488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_u += src_stride_u;
90588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_v += src_stride_v;
90688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
90788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
90888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
90988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
91088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert I422 to RGBA.
91188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
91288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I422ToRGBA(const uint8* src_y, int src_stride_y,
91388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_u, int src_stride_u,
91488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               const uint8* src_v, int src_stride_v,
91588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_rgba, int dst_stride_rgba,
91688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
91788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
91888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*I422ToRGBARow)(const uint8* y_buf,
91988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        const uint8* u_buf,
92088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        const uint8* v_buf,
92188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint8* rgb_buf,
92288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        int width) = I422ToRGBARow_C;
92388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v ||
92488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_rgba ||
92588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
92688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
92788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
92888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
92988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
93088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
93188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
93288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_rgba = -dst_stride_rgba;
93388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
93488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
93588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_y == width &&
93688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_u * 2 == width &&
93788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_v * 2 == width &&
93888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_rgba == width * 4) {
93988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
94088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
94188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = src_stride_u = src_stride_v = dst_stride_rgba = 0;
94288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
94388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_I422TORGBAROW_NEON)
94488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON)) {
94588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToRGBARow = I422ToRGBARow_Any_NEON;
94688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
94788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      I422ToRGBARow = I422ToRGBARow_NEON;
94888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
94988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
95088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_I422TORGBAROW_SSSE3)
95188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
95288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
95388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
95488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3;
95588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) {
95688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        I422ToRGBARow = I422ToRGBARow_SSSE3;
95788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
95888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
95988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
96088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
96188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
96288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
96388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width);
96488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_rgba += dst_stride_rgba;
96588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
96688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_u += src_stride_u;
96788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_v += src_stride_v;
96888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
96988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
97088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
97188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
97288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert NV12 to RGB565.
97388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
97488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint NV12ToRGB565(const uint8* src_y, int src_stride_y,
97588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 const uint8* src_uv, int src_stride_uv,
97688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint8* dst_rgb565, int dst_stride_rgb565,
97788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int width, int height) {
97888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
97988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*NV12ToRGB565Row)(const uint8* y_buf,
98088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          const uint8* uv_buf,
98188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          uint8* rgb_buf,
98288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int width) = NV12ToRGB565Row_C;
98388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_uv || !dst_rgb565 ||
98488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
98588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
98688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
98788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
98888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
98988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
99088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
99188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_rgb565 = -dst_stride_rgb565;
99288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
99388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_NV12TORGB565ROW_SSSE3)
99488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
99588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
99688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
99788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
99888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
99988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
100088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_NV12TORGB565ROW_NEON)
100188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
100288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
100388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
100488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      NV12ToRGB565Row = NV12ToRGB565Row_NEON;
100588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
100688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
100788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
100888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
100988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
101088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    NV12ToRGB565Row(src_y, src_uv, dst_rgb565, width);
101188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_rgb565 += dst_stride_rgb565;
101288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
101388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (y & 1) {
101488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_uv += src_stride_uv;
101588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
101688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
101788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
101888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
101988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
102088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert NV21 to RGB565.
102188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
102288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint NV21ToRGB565(const uint8* src_y, int src_stride_y,
102388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 const uint8* src_vu, int src_stride_vu,
102488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint8* dst_rgb565, int dst_stride_rgb565,
102588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int width, int height) {
102688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
102788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*NV21ToRGB565Row)(const uint8* y_buf,
102888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          const uint8* src_vu,
102988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          uint8* rgb_buf,
103088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int width) = NV21ToRGB565Row_C;
103188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_vu || !dst_rgb565 ||
103288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
103388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
103488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
103588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
103688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
103788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
103888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
103988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_rgb565 = -dst_stride_rgb565;
104088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
104188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_NV21TORGB565ROW_SSSE3)
104288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
104388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    NV21ToRGB565Row = NV21ToRGB565Row_Any_SSSE3;
104488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
104588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      NV21ToRGB565Row = NV21ToRGB565Row_SSSE3;
104688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
104788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
104888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_NV21TORGB565ROW_NEON)
104988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
105088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    NV21ToRGB565Row = NV21ToRGB565Row_Any_NEON;
105188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
105288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      NV21ToRGB565Row = NV21ToRGB565Row_NEON;
105388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
105488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
105588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
105688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
105788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
105888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    NV21ToRGB565Row(src_y, src_vu, dst_rgb565, width);
105988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_rgb565 += dst_stride_rgb565;
106088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
106188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (y & 1) {
106288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_vu += src_stride_vu;
106388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
106488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
106588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
106688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
106788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
106888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
106988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid SetPlane(uint8* dst_y, int dst_stride_y,
107088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int width, int height,
107188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint32 value) {
107288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
107388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint32 v32 = value | (value << 8) | (value << 16) | (value << 24);
107488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*SetRow)(uint8* dst, uint32 value, int pix) = SetRow_C;
107588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
107688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_y == width) {
107788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
107888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
107988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_y = 0;
108088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
108188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SETROW_NEON)
108288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) &&
108388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(width, 16) &&
108488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
108588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SetRow = SetRow_NEON;
108688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
108788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
108888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SETROW_X86)
108988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
109088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SetRow = SetRow_X86;
109188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
109288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
109388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
109488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Set plane
109588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
109688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SetRow(dst_y, v32, width);
109788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_y += dst_stride_y;
109888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
109988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
110088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
110188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Draw a rectangle into I420
110288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
110388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I420Rect(uint8* dst_y, int dst_stride_y,
110488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_u, int dst_stride_u,
110588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_v, int dst_stride_v,
110688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int x, int y,
110788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int width, int height,
110888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int value_y, int value_u, int value_v) {
110988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int halfwidth = (width + 1) >> 1;
111088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int halfheight = (height + 1) >> 1;
111188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* start_y = dst_y + y * dst_stride_y + x;
111288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2);
111388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2);
111488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_y || !dst_u || !dst_v ||
111588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height <= 0 ||
111688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      x < 0 || y < 0 ||
111788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      value_y < 0 || value_y > 255 ||
111888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      value_u < 0 || value_u > 255 ||
111988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      value_v < 0 || value_v > 255) {
112088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
112188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
112288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
112388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  SetPlane(start_y, dst_stride_y, width, height, value_y);
112488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  SetPlane(start_u, dst_stride_u, halfwidth, halfheight, value_u);
112588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  SetPlane(start_v, dst_stride_v, halfwidth, halfheight, value_v);
112688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
112788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
112888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
112988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Draw a rectangle into ARGB
113088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
113188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBRect(uint8* dst_argb, int dst_stride_argb,
113288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int dst_x, int dst_y,
113388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int width, int height,
113488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint32 value) {
113588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb ||
113688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height <= 0 ||
113788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_x < 0 || dst_y < 0) {
113888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
113988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
114088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  dst_argb += dst_y * dst_stride_argb + dst_x * 4;
114188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
114288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_argb == width * 4) {
114388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
114488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
114588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = 0;
114688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
114788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SETROW_NEON)
114888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16) &&
114988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
115088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSetRows_NEON(dst_argb, value, width, dst_stride_argb, height);
115188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return 0;
115288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
115388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
115488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SETROW_X86)
115588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasX86)) {
115688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSetRows_X86(dst_argb, value, width, dst_stride_argb, height);
115788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return 0;
115888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
115988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
116088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ARGBSetRows_C(dst_argb, value, width, dst_stride_argb, height);
116188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
116288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
116388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
116488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert unattentuated ARGB to preattenuated ARGB.
116588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// An unattenutated ARGB alpha blend uses the formula
116688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// p = a * f + (1 - a) * b
116788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// where
116888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//   p is output pixel
116988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//   f is foreground pixel
117088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//   b is background pixel
117188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//   a is alpha value from foreground pixel
117288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// An preattenutated ARGB alpha blend uses the formula
117388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// p = f + (1 - a) * b
117488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// where
117588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//   f is foreground pixel premultiplied by alpha
117688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
117788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
117888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBAttenuate(const uint8* src_argb, int src_stride_argb,
117988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  uint8* dst_argb, int dst_stride_argb,
118088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  int width, int height) {
118188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
118288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb,
118388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           int width) = ARGBAttenuateRow_C;
118488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
118588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
118688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
118788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
118888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
118988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
119088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
119188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
119288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
119388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
119488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
119588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
119688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
119788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
119888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
119988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBATTENUATEROW_SSE2)
120088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
120188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
120288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
120388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSE2;
120488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
120588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAttenuateRow = ARGBAttenuateRow_SSE2;
120688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
120788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
120888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
120988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBATTENUATEROW_SSSE3)
121088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) {
121188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
121288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
121388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
121488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
121588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
121688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
121788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBATTENUATEROW_AVX2)
121888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
121988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
122088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
122188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
122288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
122388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
122488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
122588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBATTENUATEROW_NEON)
122688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
122788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
122888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
122988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
123088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
123188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
123288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
123388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
123488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
123588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBAttenuateRow(src_argb, dst_argb, width);
123688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
123788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
123888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
123988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
124088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
124188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
124288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert preattentuated ARGB to unattenuated ARGB.
124388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
124488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBUnattenuate(const uint8* src_argb, int src_stride_argb,
124588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    uint8* dst_argb, int dst_stride_argb,
124688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    int width, int height) {
124788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
124888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBUnattenuateRow)(const uint8* src_argb, uint8* dst_argb,
124988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int width) = ARGBUnattenuateRow_C;
125088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
125188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
125288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
125388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
125488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
125588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
125688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
125788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
125888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
125988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
126088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
126188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
126288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
126388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
126488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
126588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBUNATTENUATEROW_SSE2)
126688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
126788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBUnattenuateRow = ARGBUnattenuateRow_Any_SSE2;
126888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
126988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBUnattenuateRow = ARGBUnattenuateRow_SSE2;
127088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
127188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
127288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
127388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBUNATTENUATEROW_AVX2)
127488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
127588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBUnattenuateRow = ARGBUnattenuateRow_Any_AVX2;
127688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
127788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBUnattenuateRow = ARGBUnattenuateRow_AVX2;
127888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
127988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
128088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
128188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// TODO(fbarchard): Neon version.
128288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
128388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
128488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBUnattenuateRow(src_argb, dst_argb, width);
128588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
128688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
128788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
128888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
128988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
129088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
129188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Convert ARGB to Grayed ARGB.
129288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
129388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBGrayTo(const uint8* src_argb, int src_stride_argb,
129488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               uint8* dst_argb, int dst_stride_argb,
129588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               int width, int height) {
129688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
129788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb,
129888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      int width) = ARGBGrayRow_C;
129988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
130088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
130188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
130288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
130388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
130488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
130588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
130688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
130788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
130888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
130988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
131088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
131188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
131288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
131388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
131488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBGRAYROW_SSSE3)
131588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
131688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
131788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
131888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBGrayRow = ARGBGrayRow_SSSE3;
131988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
132088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_ARGBGRAYROW_NEON)
132188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
132288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBGrayRow = ARGBGrayRow_NEON;
132388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
132488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
132588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
132688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
132788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBGrayRow(src_argb, dst_argb, width);
132888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
132988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
133088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
133188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
133288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
133388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
133488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Make a rectangle of ARGB gray scale.
133588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
133688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBGray(uint8* dst_argb, int dst_stride_argb,
133788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int dst_x, int dst_y,
133888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int width, int height) {
133988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
134088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb,
134188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      int width) = ARGBGrayRow_C;
134288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
134388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
134488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
134588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
134688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
134788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_argb == width * 4) {
134888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
134988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
135088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = 0;
135188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
135288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBGRAYROW_SSSE3)
135388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
135488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
135588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBGrayRow = ARGBGrayRow_SSSE3;
135688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
135788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_ARGBGRAYROW_NEON)
135888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
135988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBGrayRow = ARGBGrayRow_NEON;
136088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
136188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
136288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
136388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBGrayRow(dst, dst, width);
136488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst += dst_stride_argb;
136588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
136688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
136788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
136888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
136988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Make a rectangle of ARGB Sepia tone.
137088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
137188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBSepia(uint8* dst_argb, int dst_stride_argb,
137288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int dst_x, int dst_y, int width, int height) {
137388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
137488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBSepiaRow)(uint8* dst_argb, int width) = ARGBSepiaRow_C;
137588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
137688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
137788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
137888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
137988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
138088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_argb == width * 4) {
138188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
138288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
138388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = 0;
138488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
138588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSEPIAROW_SSSE3)
138688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
138788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
138888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSepiaRow = ARGBSepiaRow_SSSE3;
138988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
139088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_ARGBSEPIAROW_NEON)
139188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
139288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSepiaRow = ARGBSepiaRow_NEON;
139388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
139488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
139588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
139688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBSepiaRow(dst, width);
139788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst += dst_stride_argb;
139888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
139988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
140088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
140188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
140288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Apply a 4x4 matrix to each ARGB pixel.
140388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Note: Normally for shading, but can be used to swizzle or invert.
140488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
140588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBColorMatrix(const uint8* src_argb, int src_stride_argb,
140688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    uint8* dst_argb, int dst_stride_argb,
140788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    const int8* matrix_argb,
140888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    int width, int height) {
140988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
141088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBColorMatrixRow)(const uint8* src_argb, uint8* dst_argb,
141188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const int8* matrix_argb, int width) = ARGBColorMatrixRow_C;
141288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || !matrix_argb || width <= 0 || height == 0) {
141388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
141488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
141588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
141688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
141788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
141888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
141988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
142088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
142188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
142288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
142388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
142488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
142588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
142688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
142788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBCOLORMATRIXROW_SSSE3)
142888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
142988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
143088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBColorMatrixRow = ARGBColorMatrixRow_SSSE3;
143188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
143288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_ARGBCOLORMATRIXROW_NEON)
143388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
143488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBColorMatrixRow = ARGBColorMatrixRow_NEON;
143588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
143688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
143788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
143888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBColorMatrixRow(src_argb, dst_argb, matrix_argb, width);
143988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
144088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
144188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
144288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
144388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
144488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
144588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Apply a 4x3 matrix to each ARGB pixel.
144688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Deprecated.
144788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
144888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint RGBColorMatrix(uint8* dst_argb, int dst_stride_argb,
144988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   const int8* matrix_rgb,
145088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   int dst_x, int dst_y, int width, int height) {
145188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  SIMD_ALIGNED(int8 matrix_argb[16]);
145288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
145388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb || !matrix_rgb || width <= 0 || height <= 0 ||
145488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_x < 0 || dst_y < 0) {
145588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
145688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
145788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
145888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Convert 4x3 7 bit matrix to 4x4 6 bit matrix.
145988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[0] = matrix_rgb[0] / 2;
146088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[1] = matrix_rgb[1] / 2;
146188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[2] = matrix_rgb[2] / 2;
146288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[3] = matrix_rgb[3] / 2;
146388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[4] = matrix_rgb[4] / 2;
146488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[5] = matrix_rgb[5] / 2;
146588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[6] = matrix_rgb[6] / 2;
146688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[7] = matrix_rgb[7] / 2;
146788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[8] = matrix_rgb[8] / 2;
146888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[9] = matrix_rgb[9] / 2;
146988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[10] = matrix_rgb[10] / 2;
147088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[11] = matrix_rgb[11] / 2;
147188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[14] = matrix_argb[13] = matrix_argb[12] = 0;
147288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  matrix_argb[15] = 64;  // 1.0
147388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
147488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return ARGBColorMatrix((const uint8*)(dst), dst_stride_argb,
147588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         dst, dst_stride_argb,
147688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         &matrix_argb[0], width, height);
147788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
147888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
147988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Apply a color table each ARGB pixel.
148088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Table contains 256 ARGB values.
148188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
148288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBColorTable(uint8* dst_argb, int dst_stride_argb,
148388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   const uint8* table_argb,
148488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   int dst_x, int dst_y, int width, int height) {
148588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
148688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
148788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int width) = ARGBColorTableRow_C;
148888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
148988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
149088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_x < 0 || dst_y < 0) {
149188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
149288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
149388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
149488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_argb == width * 4) {
149588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
149688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
149788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = 0;
149888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
149988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBCOLORTABLEROW_X86)
150088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasX86)) {
150188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBColorTableRow = ARGBColorTableRow_X86;
150288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
150388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
150488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
150588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBColorTableRow(dst, table_argb, width);
150688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst += dst_stride_argb;
150788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
150888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
150988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
151088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
151188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Apply a color table each ARGB pixel but preserve destination alpha.
151288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Table contains 256 ARGB values.
151388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
151488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint RGBColorTable(uint8* dst_argb, int dst_stride_argb,
151588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  const uint8* table_argb,
151688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  int dst_x, int dst_y, int width, int height) {
151788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
151888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*RGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
151988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           int width) = RGBColorTableRow_C;
152088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
152188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
152288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_x < 0 || dst_y < 0) {
152388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
152488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
152588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
152688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_argb == width * 4) {
152788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
152888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
152988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = 0;
153088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
153188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_RGBCOLORTABLEROW_X86)
153288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasX86)) {
153388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    RGBColorTableRow = RGBColorTableRow_X86;
153488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
153588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
153688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
153788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    RGBColorTableRow(dst, table_argb, width);
153888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst += dst_stride_argb;
153988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
154088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
154188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
154288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
154388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// ARGBQuantize is used to posterize art.
154488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// e.g. rgb / qvalue * qvalue + qvalue / 2
154588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// But the low levels implement efficiently with 3 parameters, and could be
154688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// used for other high level operations.
154788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// dst_argb[0] = (b * scale >> 16) * interval_size + interval_offset;
154888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// where scale is 1 / interval_size as a fixed point value.
154988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// The divide is replaces with a multiply by reciprocal fixed point multiply.
155088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Caveat - although SSE2 saturates, the C function does not and should be used
155188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// with care if doing anything but quantization.
155288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
155388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBQuantize(uint8* dst_argb, int dst_stride_argb,
155488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int scale, int interval_size, int interval_offset,
155588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int dst_x, int dst_y, int width, int height) {
155688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
155788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBQuantizeRow)(uint8* dst_argb, int scale, int interval_size,
155888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int interval_offset, int width) = ARGBQuantizeRow_C;
155988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
156088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0 ||
156188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      interval_size < 1 || interval_size > 255) {
156288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
156388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
156488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
156588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_stride_argb == width * 4) {
156688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
156788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
156888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = 0;
156988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
157088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBQUANTIZEROW_SSE2)
157188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) &&
157288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
157388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBQuantizeRow = ARGBQuantizeRow_SSE2;
157488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
157588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_ARGBQUANTIZEROW_NEON)
157688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
157788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBQuantizeRow = ARGBQuantizeRow_NEON;
157888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
157988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
158088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
158188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBQuantizeRow(dst, scale, interval_size, interval_offset, width);
158288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst += dst_stride_argb;
158388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
158488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
158588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
158688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
158788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Computes table of cumulative sum for image where the value is the sum
158888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// of all values above and to the left of the entry. Used by ARGBBlur.
158988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
159088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBComputeCumulativeSum(const uint8* src_argb, int src_stride_argb,
159188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int32* dst_cumsum, int dst_stride32_cumsum,
159288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int width, int height) {
159388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
159488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ComputeCumulativeSumRow)(const uint8* row, int32* cumsum,
159588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
159688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int32* previous_cumsum = dst_cumsum;
159788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!dst_cumsum || !src_argb || width <= 0 || height <= 0) {
159888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
159988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
160088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2)
160188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2)) {
160288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2;
160388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
160488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
160588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  memset(dst_cumsum, 0, width * sizeof(dst_cumsum[0]) * 4);  // 4 int per pixel.
160688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
160788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ComputeCumulativeSumRow(src_argb, dst_cumsum, previous_cumsum, width);
160888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    previous_cumsum = dst_cumsum;
160988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_cumsum += dst_stride32_cumsum;
161088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
161188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
161288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
161388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
161488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
161588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Blur ARGB image.
161688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Caller should allocate CumulativeSum table of width * height * 16 bytes
161788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// aligned to 16 byte boundary. height can be radius * 2 + 2 to save memory
161888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// as the buffer is treated as circular.
161988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
162088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBBlur(const uint8* src_argb, int src_stride_argb,
162188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             uint8* dst_argb, int dst_stride_argb,
162288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int32* dst_cumsum, int dst_stride32_cumsum,
162388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             int width, int height, int radius) {
162488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
162588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ComputeCumulativeSumRow)(const uint8 *row, int32 *cumsum,
162688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
162788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*CumulativeSumToAverageRow)(const int32* topleft, const int32* botleft,
162888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int width, int area, uint8* dst, int count) = CumulativeSumToAverageRow_C;
162988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int32* cumsum_bot_row;
163088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int32* max_cumsum_bot_row;
163188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int32* cumsum_top_row;
163288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
163388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
163488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
163588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
163688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
163788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
163888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
163988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
164088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
164188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (radius > height) {
164288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    radius = height;
164388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
164488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (radius > (width / 2 - 1)) {
164588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    radius = width / 2 - 1;
164688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
164788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (radius <= 0) {
164888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
164988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
165088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2)
165188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2)) {
165288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2;
165388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CumulativeSumToAverageRow = CumulativeSumToAverageRow_SSE2;
165488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
165588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
165688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Compute enough CumulativeSum for first row to be blurred. After this
165788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // one row of CumulativeSum is updated at a time.
165888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ARGBComputeCumulativeSum(src_argb, src_stride_argb,
165988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           dst_cumsum, dst_stride32_cumsum,
166088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           width, radius);
166188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
166288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_argb = src_argb + radius * src_stride_argb;
166388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  cumsum_bot_row = &dst_cumsum[(radius - 1) * dst_stride32_cumsum];
166488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
166588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  max_cumsum_bot_row = &dst_cumsum[(radius * 2 + 2) * dst_stride32_cumsum];
166688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  cumsum_top_row = &dst_cumsum[0];
166788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
166888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
166988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int top_y = ((y - radius - 1) >= 0) ? (y - radius - 1) : 0;
167088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int bot_y = ((y + radius) < height) ? (y + radius) : (height - 1);
167188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int area = radius * (bot_y - top_y);
167288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int boxwidth = radius * 4;
167388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int x;
167488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int n;
167588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
167688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Increment cumsum_top_row pointer with circular buffer wrap around.
167788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (top_y) {
167888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      cumsum_top_row += dst_stride32_cumsum;
167988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (cumsum_top_row >= max_cumsum_bot_row) {
168088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        cumsum_top_row = dst_cumsum;
168188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
168288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
168388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Increment cumsum_bot_row pointer with circular buffer wrap around and
168488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // then fill in a row of CumulativeSum.
168588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if ((y + radius) < height) {
168688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const int32* prev_cumsum_bot_row = cumsum_bot_row;
168788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      cumsum_bot_row += dst_stride32_cumsum;
168888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (cumsum_bot_row >= max_cumsum_bot_row) {
168988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        cumsum_bot_row = dst_cumsum;
169088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
169188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ComputeCumulativeSumRow(src_argb, cumsum_bot_row, prev_cumsum_bot_row,
169288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                              width);
169388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_argb += src_stride_argb;
169488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
169588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
169688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Left clipped.
169788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (x = 0; x < radius + 1; ++x) {
169888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row,
169988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                boxwidth, area, &dst_argb[x * 4], 1);
170088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      area += (bot_y - top_y);
170188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      boxwidth += 4;
170288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
170388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
170488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Middle unclipped.
170588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    n = (width - 1) - radius - x + 1;
170688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row,
170788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                              boxwidth, area, &dst_argb[x * 4], n);
170888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
170988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Right clipped.
171088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (x += n; x <= width - 1; ++x) {
171188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      area -= (bot_y - top_y);
171288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      boxwidth -= 4;
171388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      CumulativeSumToAverageRow(cumsum_top_row + (x - radius - 1) * 4,
171488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                cumsum_bot_row + (x - radius - 1) * 4,
171588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                boxwidth, area, &dst_argb[x * 4], 1);
171688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
171788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
171888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
171988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
172088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
172188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
172288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Multiply ARGB image by a specified ARGB value.
172388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
172488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBShade(const uint8* src_argb, int src_stride_argb,
172588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint8* dst_argb, int dst_stride_argb,
172688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int width, int height, uint32 value) {
172788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
172888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBShadeRow)(const uint8* src_argb, uint8* dst_argb,
172988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       int width, uint32 value) = ARGBShadeRow_C;
173088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0 || value == 0u) {
173188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
173288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
173388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
173488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
173588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
173688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
173788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
173888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
173988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
174088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
174188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
174288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
174388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
174488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
174588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSHADEROW_SSE2)
174688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) &&
174788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
174888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
174988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShadeRow = ARGBShadeRow_SSE2;
175088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
175188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_ARGBSHADEROW_NEON)
175288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
175388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShadeRow = ARGBShadeRow_NEON;
175488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
175588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
175688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
175788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
175888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShadeRow(src_argb, dst_argb, width, value);
175988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
176088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
176188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
176288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
176388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
176488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
176588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Interpolate 2 ARGB images by specified amount (0 to 255).
176688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
176788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
176888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    const uint8* src_argb1, int src_stride_argb1,
176988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    uint8* dst_argb, int dst_stride_argb,
177088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    int width, int height, int interpolation) {
177188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
177288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
177388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         ptrdiff_t src_stride, int dst_width,
177488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         int source_y_fraction) = InterpolateRow_C;
177588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
177688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
177788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
177888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
177988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
178088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
178188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
178288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_stride_argb = -dst_stride_argb;
178388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
178488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
178588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb0 == width * 4 &&
178688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src_stride_argb1 == width * 4 &&
178788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
178888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
178988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
179088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
179188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
179288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_SSE2)
179388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
179488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_SSE2;
179588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
179688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_SSE2;
179788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) &&
179888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) &&
179988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
180088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_SSE2;
180188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
180288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
180388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
180488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
180588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_SSSE3)
180688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) {
180788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_SSSE3;
180888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
180988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
181088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) &&
181188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) &&
181288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
181388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_SSSE3;
181488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
181588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
181688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
181788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
181888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_AVX2)
181988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
182088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_AVX2;
182188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
182288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_AVX2;
182388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
182488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
182588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
182688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_NEON)
182788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 4) {
182888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_NEON;
182988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
183088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_NEON;
183188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
183288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
183388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
183488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
183588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && width >= 1 &&
183688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb0, 4) && IS_ALIGNED(src_stride_argb0, 4) &&
183788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb1, 4) && IS_ALIGNED(src_stride_argb1, 4) &&
183888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
183988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleARGBFilterRows = InterpolateRow_MIPS_DSPR2;
184088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
184188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
184288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
184388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
184488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow(dst_argb, src_argb0, src_argb1 - src_argb0,
184588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   width * 4, interpolation);
184688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb0 += src_stride_argb0;
184788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb1 += src_stride_argb1;
184888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
184988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
185088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
185188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
185288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
185388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Shuffle ARGB channel order.  e.g. BGRA to ARGB.
185488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
185588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBShuffle(const uint8* src_bgra, int src_stride_bgra,
185688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                uint8* dst_argb, int dst_stride_argb,
185788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                const uint8* shuffler, int width, int height) {
185888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
185988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBShuffleRow)(const uint8* src_bgra, uint8* dst_argb,
186088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         const uint8* shuffler, int pix) = ARGBShuffleRow_C;
186188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_bgra || !dst_argb ||
186288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      width <= 0 || height == 0) {
186388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
186488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
186588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
186688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
186788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
186888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_bgra = src_bgra + (height - 1) * src_stride_bgra;
186988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_bgra = -src_stride_bgra;
187088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
187188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
187288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_bgra == width * 4 &&
187388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
187488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
187588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
187688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_bgra = dst_stride_argb = 0;
187788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
187888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSHUFFLEROW_SSE2)
187988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
188088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShuffleRow = ARGBShuffleRow_Any_SSE2;
188188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
188288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBShuffleRow = ARGBShuffleRow_SSE2;
188388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
188488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
188588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
188688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSHUFFLEROW_SSSE3)
188788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
188888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShuffleRow = ARGBShuffleRow_Any_SSSE3;
188988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
189088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBShuffleRow = ARGBShuffleRow_Unaligned_SSSE3;
189188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16) &&
189288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
189388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ARGBShuffleRow = ARGBShuffleRow_SSSE3;
189488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
189588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
189688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
189788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
189888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSHUFFLEROW_AVX2)
189988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && width >= 16) {
190088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShuffleRow = ARGBShuffleRow_Any_AVX2;
190188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 16)) {
190288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBShuffleRow = ARGBShuffleRow_AVX2;
190388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
190488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
190588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
190688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBSHUFFLEROW_NEON)
190788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 4) {
190888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShuffleRow = ARGBShuffleRow_Any_NEON;
190988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 4)) {
191088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBShuffleRow = ARGBShuffleRow_NEON;
191188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
191288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
191388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
191488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
191588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
191688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBShuffleRow(src_bgra, dst_argb, shuffler, width);
191788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_bgra += src_stride_bgra;
191888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
191988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
192088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
192188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
192288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
192388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Sobel ARGB effect.
192488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic int ARGBSobelize(const uint8* src_argb, int src_stride_argb,
192588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint8* dst_argb, int dst_stride_argb,
192688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        int width, int height,
192788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        void (*SobelRow)(const uint8* src_sobelx,
192888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                         const uint8* src_sobely,
192988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                         uint8* dst, int width)) {
193088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
193188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer,
193288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         uint32 selector, int pix) = ARGBToBayerGGRow_C;
193388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1,
193488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    uint8* dst_sobely, int width) = SobelYRow_C;
193588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1,
193688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                    const uint8* src_y2, uint8* dst_sobely, int width) =
193788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      SobelXRow_C;
193888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int kEdge = 16;  // Extra pixels at start of row for extrude/align.
193988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb  || !dst_argb || width <= 0 || height == 0) {
194088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
194188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
194288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
194388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
194488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
194588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb  = src_argb  + (height - 1) * src_stride_argb;
194688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
194788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
194888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // ARGBToBayer used to select G channel from ARGB.
194988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBTOBAYERGGROW_SSE2)
195088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
195188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
195288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBToBayerRow = ARGBToBayerGGRow_Any_SSE2;
195388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
195488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBToBayerRow = ARGBToBayerGGRow_SSE2;
195588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
195688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
195788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
195888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBTOBAYERROW_SSSE3)
195988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8 &&
196088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
196188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3;
196288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
196388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBToBayerRow = ARGBToBayerRow_SSSE3;
196488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
196588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
196688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
196788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBTOBAYERGGROW_NEON)
196888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
196988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBToBayerRow = ARGBToBayerGGRow_Any_NEON;
197088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(width, 8)) {
197188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBToBayerRow = ARGBToBayerGGRow_NEON;
197288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
197388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
197488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
197588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELYROW_SSE2)
197688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2)) {
197788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelYRow = SobelYRow_SSE2;
197888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
197988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
198088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELYROW_NEON)
198188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON)) {
198288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelYRow = SobelYRow_NEON;
198388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
198488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
198588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELXROW_SSE2)
198688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2)) {
198788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelXRow = SobelXRow_SSE2;
198888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
198988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
199088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELXROW_NEON)
199188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON)) {
199288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelXRow = SobelXRow_NEON;
199388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
199488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
199588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  {
199688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // 3 rows with edges before/after.
199788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const int kRowSize = (width + kEdge + 15) & ~15;
199888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge));
199988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* row_sobelx = rows;
200088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* row_sobely = rows + kRowSize;
200188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* row_y = rows + kRowSize * 2;
200288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
200388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Convert first row.
200488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* row_y0 = row_y + kEdge;
200588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* row_y1 = row_y0 + kRowSize;
200688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* row_y2 = row_y1 + kRowSize;
200788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBToBayerRow(src_argb, row_y0, 0x0d090501, width);
200888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    row_y0[-1] = row_y0[0];
200988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    memset(row_y0 + width, row_y0[width - 1], 16);  // Extrude 16 for valgrind.
201088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBToBayerRow(src_argb, row_y1, 0x0d090501, width);
201188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    row_y1[-1] = row_y1[0];
201288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    memset(row_y1 + width, row_y1[width - 1], 16);
201388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    memset(row_y2 + width, 0, 16);
201488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
201588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (y = 0; y < height; ++y) {
201688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // Convert next row of ARGB to Y.
201788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (y < (height - 1)) {
201888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        src_argb += src_stride_argb;
201988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
202088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBToBayerRow(src_argb, row_y2, 0x0d090501, width);
202188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      row_y2[-1] = row_y2[0];
202288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      row_y2[width] = row_y2[width - 1];
202388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
202488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      SobelXRow(row_y0 - 1, row_y1 - 1, row_y2 - 1, row_sobelx, width);
202588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      SobelYRow(row_y0 - 1, row_y2 - 1, row_sobely, width);
202688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      SobelRow(row_sobelx, row_sobely, dst_argb, width);
202788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
202888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // Cycle thru circular queue of 3 row_y buffers.
202988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      {
203088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        uint8* row_yt = row_y0;
203188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        row_y0 = row_y1;
203288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        row_y1 = row_y2;
203388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        row_y2 = row_yt;
203488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
203588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
203688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_argb += dst_stride_argb;
203788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
203888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    free_aligned_buffer_64(rows);
203988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
204088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
204188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
204288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
204388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Sobel ARGB effect.
204488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
204588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBSobel(const uint8* src_argb, int src_stride_argb,
204688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint8* dst_argb, int dst_stride_argb,
204788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int width, int height) {
204888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely,
204988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   uint8* dst_argb, int width) = SobelRow_C;
205088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELROW_SSE2)
205188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) &&
205288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
205388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelRow = SobelRow_SSE2;
205488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
205588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
205688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELROW_NEON)
205788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
205888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelRow = SobelRow_NEON;
205988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
206088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
206188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
206288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      width, height, SobelRow);
206388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
206488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
206588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Sobel ARGB effect with planar output.
206688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
206788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb,
206888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     uint8* dst_y, int dst_stride_y,
206988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     int width, int height) {
207088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely,
207188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          uint8* dst_, int width) = SobelToPlaneRow_C;
207288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELTOPLANEROW_SSE2)
207388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) &&
207488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
207588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelToPlaneRow = SobelToPlaneRow_SSE2;
207688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
207788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
207888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELTOPLANEROW_NEON)
207988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
208088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelToPlaneRow = SobelToPlaneRow_NEON;
208188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
208288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
208388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y,
208488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      width, height, SobelToPlaneRow);
208588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
208688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
208788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// SobelXY ARGB effect.
208888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Similar to Sobel, but also stores Sobel X in R and Sobel Y in B.  G = Sobel.
208988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
209088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBSobelXY(const uint8* src_argb, int src_stride_argb,
209188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                uint8* dst_argb, int dst_stride_argb,
209288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                int width, int height) {
209388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely,
209488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     uint8* dst_argb, int width) = SobelXYRow_C;
209588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELXYROW_SSE2)
209688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) &&
209788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
209888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelXYRow = SobelXYRow_SSE2;
209988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
210088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
210188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SOBELXYROW_NEON)
210288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
210388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    SobelXYRow = SobelXYRow_NEON;
210488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
210588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
210688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
210788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      width, height, SobelXYRow);
210888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
210988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
211088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Apply a 4x4 polynomial to each ARGB pixel.
211188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
211288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBPolynomial(const uint8* src_argb, int src_stride_argb,
211388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   uint8* dst_argb, int dst_stride_argb,
211488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   const float* poly,
211588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   int width, int height) {
211688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
211788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBPolynomialRow)(const uint8* src_argb,
211888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            uint8* dst_argb, const float* poly,
211988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int width) = ARGBPolynomialRow_C;
212088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || !poly || width <= 0 || height == 0) {
212188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
212288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
212388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
212488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
212588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
212688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb  = src_argb  + (height - 1) * src_stride_argb;
212788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
212888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
212988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
213088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
213188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
213288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
213388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
213488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
213588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
213688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBPOLYNOMIALROW_SSE2)
213788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 2)) {
213888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBPolynomialRow = ARGBPolynomialRow_SSE2;
213988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
214088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
214188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBPOLYNOMIALROW_AVX2)
214288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && TestCpuFlag(kCpuHasFMA3) &&
214388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(width, 2)) {
214488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBPolynomialRow = ARGBPolynomialRow_AVX2;
214588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
214688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
214788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
214888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
214988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBPolynomialRow(src_argb, dst_argb, poly, width);
215088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
215188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
215288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
215388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
215488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
215588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
215688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Apply a lumacolortable to each ARGB pixel.
215788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
215888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb,
215988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       uint8* dst_argb, int dst_stride_argb,
216088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       const uint8* luma,
216188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       int width, int height) {
216288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
216388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBLumaColorTableRow)(const uint8* src_argb, uint8* dst_argb,
216488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int width, const uint8* luma, const uint32 lumacoeff) =
216588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBLumaColorTableRow_C;
216688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || !luma || width <= 0 || height == 0) {
216788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
216888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
216988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
217088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
217188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
217288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb  = src_argb  + (height - 1) * src_stride_argb;
217388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
217488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
217588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
217688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
217788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
217888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
217988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
218088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
218188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
218288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBLUMACOLORTABLEROW_SSSE3)
218388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4)) {
218488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3;
218588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
218688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
218788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
218888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
218988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBLumaColorTableRow(src_argb, dst_argb, width, luma, 0x00264b0f);
219088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
219188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
219288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
219388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
219488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
219588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
219688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Copy Alpha from one ARGB image to another.
219788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
219888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb,
219988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  uint8* dst_argb, int dst_stride_argb,
220088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  int width, int height) {
220188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
220288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBCopyAlphaRow)(const uint8* src_argb, uint8* dst_argb, int width) =
220388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBCopyAlphaRow_C;
220488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
220588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
220688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
220788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
220888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
220988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
221088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb = src_argb + (height - 1) * src_stride_argb;
221188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = -src_stride_argb;
221288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
221388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
221488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_argb == width * 4 &&
221588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
221688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
221788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
221888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_argb = dst_stride_argb = 0;
221988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
222088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBCOPYALPHAROW_SSE2)
222188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) &&
222288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
222388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) &&
222488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(width, 8)) {
222588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBCopyAlphaRow = ARGBCopyAlphaRow_SSE2;
222688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
222788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
222888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBCOPYALPHAROW_AVX2)
222988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) {
223088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBCopyAlphaRow = ARGBCopyAlphaRow_AVX2;
223188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
223288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
223388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
223488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
223588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBCopyAlphaRow(src_argb, dst_argb, width);
223688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_argb += src_stride_argb;
223788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
223888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
223988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
224088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
224188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
224288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Copy a planar Y channel to the alpha channel of a destination ARGB image.
224388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
224488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y,
224588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     uint8* dst_argb, int dst_stride_argb,
224688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     int width, int height) {
224788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
224888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ARGBCopyYToAlphaRow)(const uint8* src_y, uint8* dst_argb, int width) =
224988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ARGBCopyYToAlphaRow_C;
225088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !dst_argb || width <= 0 || height == 0) {
225188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
225288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
225388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
225488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (height < 0) {
225588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = -height;
225688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y = src_y + (height - 1) * src_stride_y;
225788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = -src_stride_y;
225888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
225988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Coalesce rows.
226088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_stride_y == width &&
226188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_stride_argb == width * 4) {
226288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    width *= height;
226388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    height = 1;
226488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride_y = dst_stride_argb = 0;
226588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
226688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBCOPYYTOALPHAROW_SSE2)
226788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) &&
226888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
226988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) &&
227088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(width, 8)) {
227188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_SSE2;
227288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
227388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
227488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_ARGBCOPYYTOALPHAROW_AVX2)
227588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) {
227688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_AVX2;
227788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
227888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
227988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
228088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < height; ++y) {
228188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ARGBCopyYToAlphaRow(src_y, dst_argb, width);
228288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_y += src_stride_y;
228388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_argb += dst_stride_argb;
228488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
228588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
228688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
228788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
228888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#ifdef __cplusplus
228988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}  // extern "C"
229088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}  // namespace libyuv
229188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
2292