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/scale.h"
1288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
1388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#include <assert.h>
1488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#include <string.h>
1588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
1641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/cpu_id.h"
1741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/planar_functions.h"  // For CopyPlane
1841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/row.h"
1941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/scale_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// Remove this macro if OVERREAD is safe.
2788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#define AVOID_OVERREAD 1
2888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
2988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic __inline int Abs(int v) {
3088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return v >= 0 ? v : -v;
3188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
3288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
3388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
3488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
3588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale plane, 1/2
3688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// This is an optimized version for scaling down a plane to 1/2 of
3788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// its original size.
3888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
3988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown2(int src_width, int src_height,
4088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int dst_width, int dst_height,
4188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int src_stride, int dst_stride,
4288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            const uint8* src_ptr, uint8* dst_ptr,
4388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            enum FilterMode filtering) {
4488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
4588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown2)(const uint8* src_ptr, ptrdiff_t src_stride,
4688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint8* dst_ptr, int dst_width) =
4788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    filtering == kFilterNone ? ScaleRowDown2_C :
4888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (filtering == kFilterLinear ? ScaleRowDown2Linear_C :
4988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2Box_C);
5088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int row_stride = src_stride << 1;
5188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
5288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;  // Point to odd rows.
5388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
5488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
5588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
5688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN2_NEON)
5788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) {
5888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2 = filtering ? ScaleRowDown2Box_NEON : ScaleRowDown2_NEON;
5988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
6088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN2_SSE2)
6188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) {
6288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_Unaligned_SSE2 :
6388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (filtering == kFilterLinear ? ScaleRowDown2Linear_Unaligned_SSE2 :
6488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2Box_Unaligned_SSE2);
6588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_ptr, 16) &&
6688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_stride, 16) && IS_ALIGNED(row_stride, 16) &&
6788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
6888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_SSE2 :
6988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          (filtering == kFilterLinear ? ScaleRowDown2Linear_SSE2 :
7088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          ScaleRowDown2Box_SSE2);
7188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
7288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
7388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN2_MIPS_DSPR2)
7488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_ptr, 4) &&
7588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_stride, 4) && IS_ALIGNED(row_stride, 4) &&
7688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
7788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2 = filtering ?
7888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2Box_MIPS_DSPR2 : ScaleRowDown2_MIPS_DSPR2;
7988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
8088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
8188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
8288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering == kFilterLinear) {
8388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
8488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
8588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // TODO(fbarchard): Loop through source height to allow odd height.
8688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height; ++y) {
8788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
8888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += row_stride;
8988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
9088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
9188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
9288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
9388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown2_16(int src_width, int src_height,
9488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int dst_width, int dst_height,
9588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int src_stride, int dst_stride,
9688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               const uint16* src_ptr, uint16* dst_ptr,
9788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               enum FilterMode filtering) {
9888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
9988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown2)(const uint16* src_ptr, ptrdiff_t src_stride,
10088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint16* dst_ptr, int dst_width) =
10188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    filtering == kFilterNone ? ScaleRowDown2_16_C :
10288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (filtering == kFilterLinear ? ScaleRowDown2Linear_16_C :
10388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2Box_16_C);
10488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int row_stride = src_stride << 1;
10588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
10688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;  // Point to odd rows.
10788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
10888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
10988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
11088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN2_16_NEON)
11188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) {
11288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2 = filtering ? ScaleRowDown2Box_16_NEON :
11388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2_16_NEON;
11488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
11588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN2_16_SSE2)
11688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) {
11788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2 = filtering == kFilterNone ?
11888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2_Unaligned_16_SSE2 :
11988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (filtering == kFilterLinear ? ScaleRowDown2Linear_Unaligned_16_SSE2 :
12088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2Box_Unaligned_16_SSE2);
12188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_ptr, 16) &&
12288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_stride, 16) && IS_ALIGNED(row_stride, 16) &&
12388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
12488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_16_SSE2 :
12588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2 :
12688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          ScaleRowDown2Box_16_SSE2);
12788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
12888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
12988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN2_16_MIPS_DSPR2)
13088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_ptr, 4) &&
13188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_stride, 4) && IS_ALIGNED(row_stride, 4) &&
13288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
13388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2 = filtering ?
13488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown2Box_16_MIPS_DSPR2 : ScaleRowDown2_16_MIPS_DSPR2;
13588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
13688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
13788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
13888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering == kFilterLinear) {
13988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
14088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
14188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // TODO(fbarchard): Loop through source height to allow odd height.
14288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height; ++y) {
14388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
14488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += row_stride;
14588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
14688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
14788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
14888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
14988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale plane, 1/4
15088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// This is an optimized version for scaling down a plane to 1/4 of
15188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// its original size.
15288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
15388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown4(int src_width, int src_height,
15488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int dst_width, int dst_height,
15588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int src_stride, int dst_stride,
15688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            const uint8* src_ptr, uint8* dst_ptr,
15788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            enum FilterMode filtering) {
15888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
15988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown4)(const uint8* src_ptr, ptrdiff_t src_stride,
16088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint8* dst_ptr, int dst_width) =
16188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      filtering ? ScaleRowDown4Box_C : ScaleRowDown4_C;
16288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int row_stride = src_stride << 2;
16388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
16488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 2;  // Point to row 2.
16588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
16688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
16788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN4_NEON)
16888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) {
16988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON;
17088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
17188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN4_SSE2)
17288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) &&
17388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_width, 8) && IS_ALIGNED(row_stride, 16) &&
17488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
17588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSE2 : ScaleRowDown4_SSE2;
17688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
17788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN4_MIPS_DSPR2)
17888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(row_stride, 4) &&
17988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) &&
18088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
18188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4 = filtering ?
18288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown4Box_MIPS_DSPR2 : ScaleRowDown4_MIPS_DSPR2;
18388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
18488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
18588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
18688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering == kFilterLinear) {
18788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
18888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
18988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height; ++y) {
19088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
19188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += row_stride;
19288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
19388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
19488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
19588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
19688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown4_16(int src_width, int src_height,
19788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int dst_width, int dst_height,
19888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int src_stride, int dst_stride,
19988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               const uint16* src_ptr, uint16* dst_ptr,
20088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               enum FilterMode filtering) {
20188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
20288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown4)(const uint16* src_ptr, ptrdiff_t src_stride,
20388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                        uint16* dst_ptr, int dst_width) =
20488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      filtering ? ScaleRowDown4Box_16_C : ScaleRowDown4_16_C;
20588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int row_stride = src_stride << 2;
20688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
20788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 2;  // Point to row 2.
20888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
20988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
21088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN4_16_NEON)
21188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) {
21288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_NEON :
21388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown4_16_NEON;
21488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
21588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN4_16_SSE2)
21688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) &&
21788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_width, 8) && IS_ALIGNED(row_stride, 16) &&
21888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
21988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_SSE2 :
22088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown4_16_SSE2;
22188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
22288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN4_16_MIPS_DSPR2)
22388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(row_stride, 4) &&
22488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) &&
22588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
22688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4 = filtering ?
22788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        ScaleRowDown4Box_16_MIPS_DSPR2 : ScaleRowDown4_16_MIPS_DSPR2;
22888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
22988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
23088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
23188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering == kFilterLinear) {
23288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = 0;
23388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
23488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height; ++y) {
23588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
23688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += row_stride;
23788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
23888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
23988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
24088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
24188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale plane down, 3/4
24288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
24388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown34(int src_width, int src_height,
24488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int dst_width, int dst_height,
24588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int src_stride, int dst_stride,
24688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             const uint8* src_ptr, uint8* dst_ptr,
24788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             enum FilterMode filtering) {
24888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
24988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown34_0)(const uint8* src_ptr, ptrdiff_t src_stride,
25088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint8* dst_ptr, int dst_width);
25188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown34_1)(const uint8* src_ptr, ptrdiff_t src_stride,
25288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint8* dst_ptr, int dst_width);
25388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
25488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(dst_width % 3 == 0);
25588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
25688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0 = ScaleRowDown34_C;
25788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1 = ScaleRowDown34_C;
25888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else {
25988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0 = ScaleRowDown34_0_Box_C;
26088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1 = ScaleRowDown34_1_Box_C;
26188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
26288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN34_NEON)
26388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) {
26488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
26588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_NEON;
26688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_NEON;
26788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
26888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON;
26988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON;
27088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
27188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
27288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
27388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN34_SSSE3)
27488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) &&
27588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
27688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
27788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_SSSE3;
27888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_SSSE3;
27988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
28088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3;
28188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3;
28288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
28388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
28488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
28588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN34_MIPS_DSPR2)
28688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && (dst_width % 24 == 0) &&
28788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) &&
28888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
28988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
29088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_MIPS_DSPR2;
29188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_MIPS_DSPR2;
29288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
29388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_0_Box_MIPS_DSPR2;
29488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_1_Box_MIPS_DSPR2;
29588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
29688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
29788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
29888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
29988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height - 2; y += 3) {
30088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
30188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
30288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
30388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width);
30488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
30588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
30688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr + src_stride, -filter_stride,
30788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     dst_ptr, dst_width);
30888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 2;
30988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
31088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
31188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
31288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Remainder 1 or 2 rows with last row vertically unfiltered
31388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if ((dst_height % 3) == 2) {
31488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
31588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
31688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
31788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width);
31888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else if ((dst_height % 3) == 1) {
31988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width);
32088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
32188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
32288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
32388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown34_16(int src_width, int src_height,
32488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                int dst_width, int dst_height,
32588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                int src_stride, int dst_stride,
32688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                const uint16* src_ptr, uint16* dst_ptr,
32788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                enum FilterMode filtering) {
32888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
32988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown34_0)(const uint16* src_ptr, ptrdiff_t src_stride,
33088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint16* dst_ptr, int dst_width);
33188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown34_1)(const uint16* src_ptr, ptrdiff_t src_stride,
33288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint16* dst_ptr, int dst_width);
33388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
33488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(dst_width % 3 == 0);
33588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
33688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0 = ScaleRowDown34_16_C;
33788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1 = ScaleRowDown34_16_C;
33888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else {
33988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_C;
34088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_C;
34188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
34288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN34_16_NEON)
34388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) {
34488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
34588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_16_NEON;
34688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_16_NEON;
34788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
34888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_NEON;
34988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_NEON;
35088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
35188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
35288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
35388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN34_16_SSSE3)
35488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) &&
35588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
35688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
35788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_16_SSSE3;
35888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_16_SSSE3;
35988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
36088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_SSSE3;
36188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_SSSE3;
36288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
36388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
36488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
36588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN34_16_MIPS_DSPR2)
36688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && (dst_width % 24 == 0) &&
36788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) &&
36888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
36988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
37088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_16_MIPS_DSPR2;
37188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_16_MIPS_DSPR2;
37288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
37388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_MIPS_DSPR2;
37488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_MIPS_DSPR2;
37588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
37688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
37788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
37888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
37988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height - 2; y += 3) {
38088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
38188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
38288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
38388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width);
38488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
38588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
38688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr + src_stride, -filter_stride,
38788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     dst_ptr, dst_width);
38888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 2;
38988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
39088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
39188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
39288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Remainder 1 or 2 rows with last row vertically unfiltered
39388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if ((dst_height % 3) == 2) {
39488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
39588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
39688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
39788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width);
39888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else if ((dst_height % 3) == 1) {
39988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width);
40088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
40188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
40288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
40388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
40488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale plane, 3/8
40588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// This is an optimized version for scaling down a plane to 3/8
40688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// of its original size.
40788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//
40888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Uses box filter arranges like this
40988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// aaabbbcc -> abc
41088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// aaabbbcc    def
41188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// aaabbbcc    ghi
41288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// dddeeeff
41388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// dddeeeff
41488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// dddeeeff
41588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// ggghhhii
41688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// ggghhhii
41788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Boxes are 3x3, 2x3, 3x2 and 2x2
41888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
41988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown38(int src_width, int src_height,
42088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int dst_width, int dst_height,
42188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int src_stride, int dst_stride,
42288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             const uint8* src_ptr, uint8* dst_ptr,
42388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             enum FilterMode filtering) {
42488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
42588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown38_3)(const uint8* src_ptr, ptrdiff_t src_stride,
42688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint8* dst_ptr, int dst_width);
42788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown38_2)(const uint8* src_ptr, ptrdiff_t src_stride,
42888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint8* dst_ptr, int dst_width);
42988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
43088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(dst_width % 3 == 0);
43188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
43288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3 = ScaleRowDown38_C;
43388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_2 = ScaleRowDown38_C;
43488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else {
43588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3 = ScaleRowDown38_3_Box_C;
43688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_2 = ScaleRowDown38_2_Box_C;
43788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
43888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN38_NEON)
43988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && (dst_width % 12 == 0)) {
44088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
44188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_NEON;
44288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_NEON;
44388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
44488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_3_Box_NEON;
44588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_2_Box_NEON;
44688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
44788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
44888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN38_SSSE3)
44988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) &&
45088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
45188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
45288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_SSSE3;
45388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_SSSE3;
45488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
45588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_3_Box_SSSE3;
45688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_2_Box_SSSE3;
45788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
45888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
45988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN38_MIPS_DSPR2)
46088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && (dst_width % 12 == 0) &&
46188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) &&
46288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
46388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
46488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_MIPS_DSPR2;
46588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_MIPS_DSPR2;
46688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
46788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_3_Box_MIPS_DSPR2;
46888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_2_Box_MIPS_DSPR2;
46988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
47088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
47188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
47288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
47388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height - 2; y += 3) {
47488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
47588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 3;
47688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
47788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
47888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 3;
47988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
48088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width);
48188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 2;
48288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
48388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
48488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
48588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Remainder 1 or 2 rows with last row vertically unfiltered
48688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if ((dst_height % 3) == 2) {
48788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
48888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 3;
48988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
49088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
49188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else if ((dst_height % 3) == 1) {
49288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
49388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
49488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
49588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
49688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneDown38_16(int src_width, int src_height,
49788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                int dst_width, int dst_height,
49888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                int src_stride, int dst_stride,
49988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                const uint16* src_ptr, uint16* dst_ptr,
50088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                enum FilterMode filtering) {
50188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
50288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown38_3)(const uint16* src_ptr, ptrdiff_t src_stride,
50388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint16* dst_ptr, int dst_width);
50488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleRowDown38_2)(const uint16* src_ptr, ptrdiff_t src_stride,
50588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           uint16* dst_ptr, int dst_width);
50688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
50788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(dst_width % 3 == 0);
50888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering) {
50988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3 = ScaleRowDown38_16_C;
51088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_2 = ScaleRowDown38_16_C;
51188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else {
51288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_C;
51388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_C;
51488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
51588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEROWDOWN38_16_NEON)
51688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && (dst_width % 12 == 0)) {
51788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
51888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_16_NEON;
51988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_16_NEON;
52088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
52188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_NEON;
52288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_NEON;
52388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
52488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
52588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN38_16_SSSE3)
52688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0) &&
52788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
52888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
52988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_16_SSSE3;
53088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_16_SSSE3;
53188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
53288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_SSSE3;
53388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_SSSE3;
53488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
53588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
53688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#elif defined(HAS_SCALEROWDOWN38_16_MIPS_DSPR2)
53788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && (dst_width % 12 == 0) &&
53888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(src_ptr, 4) && IS_ALIGNED(src_stride, 4) &&
53988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
54088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (!filtering) {
54188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_16_MIPS_DSPR2;
54288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_16_MIPS_DSPR2;
54388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
54488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_MIPS_DSPR2;
54588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_MIPS_DSPR2;
54688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
54788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
54888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
54988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
55088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < dst_height - 2; y += 3) {
55188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
55288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 3;
55388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
55488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
55588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 3;
55688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
55788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width);
55888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 2;
55988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
56088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
56188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
56288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Remainder 1 or 2 rows with last row vertically unfiltered
56388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if ((dst_height % 3) == 2) {
56488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
56588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride * 3;
56688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
56788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
56888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  } else if ((dst_height % 3) == 1) {
56988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
57088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
57188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
57288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
57388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic __inline uint32 SumBox(int iboxwidth, int iboxheight,
57488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                              ptrdiff_t src_stride, const uint8* src_ptr) {
57588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint32 sum = 0u;
57688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
57788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(iboxwidth > 0);
57888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(iboxheight > 0);
57988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < iboxheight; ++y) {
58088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int x;
58188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (x = 0; x < iboxwidth; ++x) {
58288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      sum += src_ptr[x];
58388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
58488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
58588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
58688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return sum;
58788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
58888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
58988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic __inline uint32 SumBox_16(int iboxwidth, int iboxheight,
59088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                 ptrdiff_t src_stride, const uint16* src_ptr) {
59188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint32 sum = 0u;
59288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y;
59388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(iboxwidth > 0);
59488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(iboxheight > 0);
59588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (y = 0; y < iboxheight; ++y) {
59688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int x;
59788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (x = 0; x < iboxwidth; ++x) {
59888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      sum += src_ptr[x];
59988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
60088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_ptr += src_stride;
60188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
60288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return sum;
60388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
60488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
60588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneBoxRow_C(int dst_width, int boxheight,
60688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int x, int dx, ptrdiff_t src_stride,
60788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               const uint8* src_ptr, uint8* dst_ptr) {
60888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
60988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int boxwidth;
61088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_width; ++i) {
61188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int ix = x >> 16;
61288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    x += dx;
61388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    boxwidth = (x >> 16) - ix;
61488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    *dst_ptr++ = SumBox(boxwidth, boxheight, src_stride, src_ptr + ix) /
61588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (boxwidth * boxheight);
61688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
61788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
61888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
61988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneBoxRow_16_C(int dst_width, int boxheight,
62088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                  int x, int dx, ptrdiff_t src_stride,
62188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                  const uint16* src_ptr, uint16* dst_ptr) {
62288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
62388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int boxwidth;
62488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_width; ++i) {
62588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int ix = x >> 16;
62688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    x += dx;
62788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    boxwidth = (x >> 16) - ix;
62888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    *dst_ptr++ = SumBox_16(boxwidth, boxheight, src_stride, src_ptr + ix) /
62988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (boxwidth * boxheight);
63088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
63188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
63288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
63388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic __inline uint32 SumPixels(int iboxwidth, const uint16* src_ptr) {
63488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint32 sum = 0u;
63588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x;
63688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(iboxwidth > 0);
63788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (x = 0; x < iboxwidth; ++x) {
63888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    sum += src_ptr[x];
63988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
64088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return sum;
64188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
64288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
64388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic __inline uint32 SumPixels_16(int iboxwidth, const uint32* src_ptr) {
64488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint32 sum = 0u;
64588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x;
64688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  assert(iboxwidth > 0);
64788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (x = 0; x < iboxwidth; ++x) {
64888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    sum += src_ptr[x];
64988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
65088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return sum;
65188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
65288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
65388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScaleAddCols2_C(int dst_width, int boxheight, int x, int dx,
65488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            const uint16* src_ptr, uint8* dst_ptr) {
65588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
65688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int scaletbl[2];
65788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int minboxwidth = (dx >> 16);
65888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int* scaleptr = scaletbl - minboxwidth;
65988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int boxwidth;
66088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  scaletbl[0] = 65536 / (minboxwidth * boxheight);
66188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  scaletbl[1] = 65536 / ((minboxwidth + 1) * boxheight);
66288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_width; ++i) {
66388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int ix = x >> 16;
66488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    x += dx;
66588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    boxwidth = (x >> 16) - ix;
66688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    *dst_ptr++ = SumPixels(boxwidth, src_ptr + ix) * scaleptr[boxwidth] >> 16;
66788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
66888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
66988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
67088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScaleAddCols2_16_C(int dst_width, int boxheight, int x, int dx,
67188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               const uint32* src_ptr, uint16* dst_ptr) {
67288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
67388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int scaletbl[2];
67488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int minboxwidth = (dx >> 16);
67588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int* scaleptr = scaletbl - minboxwidth;
67688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int boxwidth;
67788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  scaletbl[0] = 65536 / (minboxwidth * boxheight);
67888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  scaletbl[1] = 65536 / ((minboxwidth + 1) * boxheight);
67988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_width; ++i) {
68088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int ix = x >> 16;
68188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    x += dx;
68288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    boxwidth = (x >> 16) - ix;
68388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + ix) *
68488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        scaleptr[boxwidth] >> 16;
68588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
68688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
68788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
68888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScaleAddCols1_C(int dst_width, int boxheight, int x, int dx,
68988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            const uint16* src_ptr, uint8* dst_ptr) {
69088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int boxwidth = (dx >> 16);
69188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int scaleval = 65536 / (boxwidth * boxheight);
69288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
69388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_width; ++i) {
69488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    *dst_ptr++ = SumPixels(boxwidth, src_ptr + x) * scaleval >> 16;
69588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    x += boxwidth;
69688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
69788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
69888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
69988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScaleAddCols1_16_C(int dst_width, int boxheight, int x, int dx,
70088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               const uint32* src_ptr, uint16* dst_ptr) {
70188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int boxwidth = (dx >> 16);
70288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int scaleval = 65536 / (boxwidth * boxheight);
70388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
70488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_width; ++i) {
70588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + x) * scaleval >> 16;
70688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    x += boxwidth;
70788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
70888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
70988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
71088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale plane down to any dimensions, with interpolation.
71188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// (boxfilter).
71288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org//
71388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Same method as SimpleScale, which is fixed point, outputting
71488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// one pixel of destination using fixed point (16.16) to step
71588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// through source, sampling a box of pixel with simple
71688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// averaging.
71788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneBox(int src_width, int src_height,
71888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int dst_width, int dst_height,
71988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int src_stride, int dst_stride,
72088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          const uint8* src_ptr, uint8* dst_ptr) {
72188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int j;
72288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
72388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
72488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
72588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
72688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
72788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int max_y = (src_height << 16);
72888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox,
72988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
73088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
73188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // TODO(fbarchard): Remove this and make AddRows handle boxheight 1.
73288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!IS_ALIGNED(src_width, 16) || dst_height * 2 > src_height) {
73388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* dst = dst_ptr;
73488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int j;
73588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (j = 0; j < dst_height; ++j) {
73688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int boxheight;
73788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int iy = y >> 16;
73888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const uint8* src = src_ptr + iy * src_stride;
73988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y += dy;
74088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (y > max_y) {
74188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        y = max_y;
74288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
74388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      boxheight = (y >> 16) - iy;
74488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneBoxRow_C(dst_width, boxheight,
74588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         x, dx, src_stride,
74688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         src, dst);
74788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst += dst_stride;
74888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
74988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
75088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
75188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  {
75288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Allocate a row buffer of uint16.
75388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    align_buffer_64(row16, src_width * 2);
75488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx,
75588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        const uint16* src_ptr, uint8* dst_ptr) =
75688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (dx & 0xffff) ? ScaleAddCols2_C: ScaleAddCols1_C;
75788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    void (*ScaleAddRows)(const uint8* src_ptr, ptrdiff_t src_stride,
75888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        uint16* dst_ptr, int src_width, int src_height) = ScaleAddRows_C;
75988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
76088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEADDROWS_SSE2)
76188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (TestCpuFlag(kCpuHasSSE2) &&
76288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#ifdef AVOID_OVERREAD
76388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_width, 16) &&
76488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
76588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
76688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleAddRows = ScaleAddRows_SSE2;
76788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
76888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
76988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
77088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (j = 0; j < dst_height; ++j) {
77188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int boxheight;
77288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int iy = y >> 16;
77388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const uint8* src = src_ptr + iy * src_stride;
77488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y += dy;
77588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (y > (src_height << 16)) {
77688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        y = (src_height << 16);
77788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
77888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      boxheight = (y >> 16) - iy;
77988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleAddRows(src, src_stride, (uint16*)(row16),
78088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 src_width, boxheight);
78188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleAddCols(dst_width, boxheight, x, dx, (uint16*)(row16),
78288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 dst_ptr);
78388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_ptr += dst_stride;
78488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
78588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    free_aligned_buffer_64(row16);
78688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
78788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
78888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
78988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneBox_16(int src_width, int src_height,
79088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int dst_width, int dst_height,
79188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int src_stride, int dst_stride,
79288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             const uint16* src_ptr, uint16* dst_ptr) {
79388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int j;
79488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
79588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
79688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
79788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
79888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
79988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int max_y = (src_height << 16);
80088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox,
80188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
80288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
80388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // TODO(fbarchard): Remove this and make AddRows handle boxheight 1.
80488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!IS_ALIGNED(src_width, 16) || dst_height * 2 > src_height) {
80588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint16* dst = dst_ptr;
80688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int j;
80788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (j = 0; j < dst_height; ++j) {
80888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int boxheight;
80988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int iy = y >> 16;
81088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const uint16* src = src_ptr + iy * src_stride;
81188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y += dy;
81288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (y > max_y) {
81388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        y = max_y;
81488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
81588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      boxheight = (y >> 16) - iy;
81688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneBoxRow_16_C(dst_width, boxheight,
81788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            x, dx, src_stride,
81888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            src, dst);
81988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst += dst_stride;
82088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
82188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
82288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
82388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  {
82488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Allocate a row buffer of uint32.
82588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    align_buffer_64(row32, src_width * 4);
82688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx,
82788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        const uint32* src_ptr, uint16* dst_ptr) =
82888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        (dx & 0xffff) ? ScaleAddCols2_16_C: ScaleAddCols1_16_C;
82988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    void (*ScaleAddRows)(const uint16* src_ptr, ptrdiff_t src_stride,
83088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        uint32* dst_ptr, int src_width, int src_height) = ScaleAddRows_16_C;
83188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
83288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEADDROWS_16_SSE2)
83388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (TestCpuFlag(kCpuHasSSE2) &&
83488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#ifdef AVOID_OVERREAD
83588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_width, 16) &&
83688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
83788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
83888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleAddRows = ScaleAddRows_16_SSE2;
83988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
84088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
84188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
84288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (j = 0; j < dst_height; ++j) {
84388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int boxheight;
84488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int iy = y >> 16;
84588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      const uint16* src = src_ptr + iy * src_stride;
84688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y += dy;
84788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (y > (src_height << 16)) {
84888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        y = (src_height << 16);
84988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
85088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      boxheight = (y >> 16) - iy;
85188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleAddRows(src, src_stride, (uint32*)(row32),
85288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 src_width, boxheight);
85388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleAddCols(dst_width, boxheight, x, dx, (uint32*)(row32),
85488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 dst_ptr);
85588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_ptr += dst_stride;
85688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
85788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    free_aligned_buffer_64(row32);
85888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
85988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
86088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
86188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale plane down with bilinear interpolation.
86288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid ScalePlaneBilinearDown(int src_width, int src_height,
86388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int dst_width, int dst_height,
86488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            int src_stride, int dst_stride,
86588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            const uint8* src_ptr, uint8* dst_ptr,
86688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            enum FilterMode filtering) {
86788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
86888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
86988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
87088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
87188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
87288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
87388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Allocate a row buffer.
87488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  align_buffer_64(row, src_width);
87588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
87688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int max_y = (src_height - 1) << 16;
87788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int j;
87888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleFilterCols)(uint8* dst_ptr, const uint8* src_ptr,
87988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int dst_width, int x, int dx) =
88088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      (src_width >= 32768) ? ScaleFilterCols64_C : ScaleFilterCols_C;
88188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
88288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
88388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow_C;
88488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, filtering,
88588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
88688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
88788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
88888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_SSE2)
88988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && src_width >= 16) {
89088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_SSE2;
89188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 16)) {
89288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_SSE2;
89388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
89488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_SSE2;
89588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
89688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
89788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
89888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
89988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_SSSE3)
90088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 16) {
90188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_SSSE3;
90288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 16)) {
90388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
90488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
90588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_SSSE3;
90688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
90788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
90888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
90988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
91088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_AVX2)
91188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && src_width >= 32) {
91288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_AVX2;
91388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 32)) {
91488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_AVX2;
91588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
91688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
91788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
91888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_NEON)
91988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && src_width >= 16) {
92088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_NEON;
92188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 16)) {
92288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_NEON;
92388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
92488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
92588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
92688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2)
92788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && src_width >= 4) {
92888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_MIPS_DSPR2;
92988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 4)) {
93088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_MIPS_DSPR2;
93188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
93288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
93388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
93488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
93588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
93688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEFILTERCOLS_SSSE3)
93788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
93888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleFilterCols_SSSE3;
93988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
94088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
94188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (y > max_y) {
94288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y = max_y;
94388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
94488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
94588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (j = 0; j < dst_height; ++j) {
94688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int yi = y >> 16;
94788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const uint8* src = src_ptr + yi * src_stride;
94888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (filtering == kFilterLinear) {
94988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleFilterCols(dst_ptr, src, dst_width, x, dx);
95088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
95188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int yf = (y >> 8) & 255;
95288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow(row, src, src_stride, src_width, yf);
95388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleFilterCols(dst_ptr, row, dst_width, x, dx);
95488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
95588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
95688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y += dy;
95788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (y > max_y) {
95888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y = max_y;
95988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
96088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
96188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  free_aligned_buffer_64(row);
96288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
96388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
96488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid ScalePlaneBilinearDown_16(int src_width, int src_height,
96588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int dst_width, int dst_height,
96688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               int src_stride, int dst_stride,
96788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               const uint16* src_ptr, uint16* dst_ptr,
96888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                               enum FilterMode filtering) {
96988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
97088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
97188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
97288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
97388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
97488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
97588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Allocate a row buffer.
97688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  align_buffer_64(row, src_width * 2);
97788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
97888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int max_y = (src_height - 1) << 16;
97988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int j;
98088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleFilterCols)(uint16* dst_ptr, const uint16* src_ptr,
98188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int dst_width, int x, int dx) =
98288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      (src_width >= 32768) ? ScaleFilterCols64_16_C : ScaleFilterCols_16_C;
98388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*InterpolateRow)(uint16* dst_ptr, const uint16* src_ptr,
98488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
98588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow_16_C;
98688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, filtering,
98788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
98888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
98988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
99088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_SSE2)
99188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && src_width >= 16) {
99288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_SSE2;
99388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 16)) {
99488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_16_SSE2;
99588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
99688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_16_SSE2;
99788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
99888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
99988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
100088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
100188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_SSSE3)
100288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 16) {
100388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_SSSE3;
100488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 16)) {
100588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_16_SSSE3;
100688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16)) {
100788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_16_SSSE3;
100888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
100988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
101088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
101188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
101288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_AVX2)
101388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && src_width >= 32) {
101488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_AVX2;
101588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 32)) {
101688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_16_AVX2;
101788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
101888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
101988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
102088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_NEON)
102188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && src_width >= 16) {
102288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_NEON;
102388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 16)) {
102488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_16_NEON;
102588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
102688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
102788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
102888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_MIPS_DSPR2)
102988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && src_width >= 4) {
103088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_MIPS_DSPR2;
103188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(src_width, 4)) {
103288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_16_MIPS_DSPR2;
103388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
103488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
103588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
103688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
103788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
103888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEFILTERCOLS_16_SSSE3)
103988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
104088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleFilterCols_16_SSSE3;
104188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
104288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
104388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (y > max_y) {
104488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y = max_y;
104588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
104688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
104788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (j = 0; j < dst_height; ++j) {
104888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int yi = y >> 16;
104988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const uint16* src = src_ptr + yi * src_stride;
105088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (filtering == kFilterLinear) {
105188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleFilterCols(dst_ptr, src, dst_width, x, dx);
105288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    } else {
105388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int yf = (y >> 8) & 255;
105488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow((uint16*)row, src, src_stride, src_width, yf);
105588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleFilterCols(dst_ptr, (uint16*)row, dst_width, x, dx);
105688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
105788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
105888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y += dy;
105988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (y > max_y) {
106088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y = max_y;
106188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
106288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
106388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  free_aligned_buffer_64(row);
106488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
106588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
106688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale up down with bilinear interpolation.
106788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid ScalePlaneBilinearUp(int src_width, int src_height,
106888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int dst_width, int dst_height,
106988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          int src_stride, int dst_stride,
107088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          const uint8* src_ptr, uint8* dst_ptr,
107188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          enum FilterMode filtering) {
107288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int j;
107388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
107488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
107588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
107688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
107788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
107888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int max_y = (src_height - 1) << 16;
107988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
108088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
108188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow_C;
108288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleFilterCols)(uint8* dst_ptr, const uint8* src_ptr,
108388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org       int dst_width, int x, int dx) =
108488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org       filtering ? ScaleFilterCols_C : ScaleCols_C;
108588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, filtering,
108688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
108788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
108888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
108988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_SSE2)
109088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 16) {
109188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_SSE2;
109288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 16)) {
109388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_SSE2;
109488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
109588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_SSE2;
109688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
109788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
109888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
109988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
110088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_SSSE3)
110188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 16) {
110288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_SSSE3;
110388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 16)) {
110488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
110588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
110688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_SSSE3;
110788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
110888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
110988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
111088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
111188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_AVX2)
111288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 32) {
111388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_AVX2;
111488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 32)) {
111588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_AVX2;
111688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
111788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
111888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
111988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_NEON)
112088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && dst_width >= 16) {
112188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_NEON;
112288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 16)) {
112388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_NEON;
112488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
112588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
112688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
112788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_MIPS_DSPR2)
112888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 4) {
112988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_MIPS_DSPR2;
113088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 4)) {
113188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_MIPS_DSPR2;
113288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
113388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
113488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
113588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
113688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering && src_width >= 32768) {
113788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleFilterCols64_C;
113888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
113988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEFILTERCOLS_SSSE3)
114088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
114188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleFilterCols_SSSE3;
114288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
114388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
114488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
114588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleColsUp2_C;
114688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALECOLS_SSE2)
114788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
114888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
114988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
115088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleFilterCols = ScaleColsUp2_SSE2;
115188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
115288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
115388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
115488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
115588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (y > max_y) {
115688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y = max_y;
115788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
115888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  {
115988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int yi = y >> 16;
116088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const uint8* src = src_ptr + yi * src_stride;
116188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
116288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Allocate 2 row buffers.
116388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const int kRowSize = (dst_width + 15) & ~15;
116488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    align_buffer_64(row, kRowSize * 2);
116588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
116688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint8* rowptr = row;
116788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int rowstride = kRowSize;
116888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int lasty = yi;
116988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
117088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols(rowptr, src, dst_width, x, dx);
117188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (src_height > 1) {
117288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src += src_stride;
117388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
117488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx);
117588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src += src_stride;
117688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
117788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (j = 0; j < dst_height; ++j) {
117888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      yi = y >> 16;
117988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (yi != lasty) {
118088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        if (y > max_y) {
118188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          y = max_y;
118288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          yi = y >> 16;
118388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          src = src_ptr + yi * src_stride;
118488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        }
118588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        if (yi != lasty) {
118688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          ScaleFilterCols(rowptr, src, dst_width, x, dx);
118788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          rowptr += rowstride;
118888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          rowstride = -rowstride;
118988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          lasty = yi;
119088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          src += src_stride;
119188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        }
119288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
119388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (filtering == kFilterLinear) {
119488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0);
119588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      } else {
119688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        int yf = (y >> 8) & 255;
119788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf);
119888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
119988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_ptr += dst_stride;
120088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y += dy;
120188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
120288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    free_aligned_buffer_64(row);
120388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
120488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
120588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
120688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid ScalePlaneBilinearUp_16(int src_width, int src_height,
120788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int dst_width, int dst_height,
120888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int src_stride, int dst_stride,
120988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             const uint16* src_ptr, uint16* dst_ptr,
121088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             enum FilterMode filtering) {
121188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int j;
121288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
121388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
121488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
121588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
121688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
121788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const int max_y = (src_height - 1) << 16;
121888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*InterpolateRow)(uint16* dst_ptr, const uint16* src_ptr,
121988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
122088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow_16_C;
122188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleFilterCols)(uint16* dst_ptr, const uint16* src_ptr,
122288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org       int dst_width, int x, int dx) =
122388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org       filtering ? ScaleFilterCols_16_C : ScaleCols_16_C;
122488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, filtering,
122588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
122688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
122788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
122888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_SSE2)
122988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 16) {
123088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_SSE2;
123188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 16)) {
123288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_16_SSE2;
123388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
123488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_16_SSE2;
123588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
123688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
123788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
123888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
123988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_SSSE3)
124088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 16) {
124188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_SSSE3;
124288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 16)) {
124388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_Unaligned_16_SSSE3;
124488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
124588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow = InterpolateRow_16_SSSE3;
124688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
124788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
124888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
124988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
125088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_AVX2)
125188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 32) {
125288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_AVX2;
125388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 32)) {
125488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_16_AVX2;
125588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
125688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
125788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
125888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_NEON)
125988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasNEON) && dst_width >= 16) {
126088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_NEON;
126188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 16)) {
126288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_16_NEON;
126388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
126488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
126588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
126688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_INTERPOLATEROW_16_MIPS_DSPR2)
126788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 4) {
126888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    InterpolateRow = InterpolateRow_Any_16_MIPS_DSPR2;
126988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (IS_ALIGNED(dst_width, 4)) {
127088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      InterpolateRow = InterpolateRow_16_MIPS_DSPR2;
127188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
127288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
127388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
127488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
127588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering && src_width >= 32768) {
127688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleFilterCols64_16_C;
127788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
127888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALEFILTERCOLS_16_SSSE3)
127988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
128088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleFilterCols_16_SSSE3;
128188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
128288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
128388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
128488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols = ScaleColsUp2_16_C;
128588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALECOLS_16_SSE2)
128688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
128788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
128888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
128988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleFilterCols = ScaleColsUp2_16_SSE2;
129088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
129188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
129288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
129388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
129488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (y > max_y) {
129588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y = max_y;
129688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
129788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  {
129888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int yi = y >> 16;
129988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const uint16* src = src_ptr + yi * src_stride;
130088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
130188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Allocate 2 row buffers.
130288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    const int kRowSize = (dst_width + 15) & ~15;
130388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    align_buffer_64(row, kRowSize * 4);
130488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
130588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    uint16* rowptr = (uint16*)row;
130688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int rowstride = kRowSize;
130788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int lasty = yi;
130888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
130988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols(rowptr, src, dst_width, x, dx);
131088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (src_height > 1) {
131188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      src += src_stride;
131288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
131388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx);
131488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src += src_stride;
131588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
131688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    for (j = 0; j < dst_height; ++j) {
131788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      yi = y >> 16;
131888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (yi != lasty) {
131988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        if (y > max_y) {
132088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          y = max_y;
132188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          yi = y >> 16;
132288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          src = src_ptr + yi * src_stride;
132388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        }
132488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        if (yi != lasty) {
132588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          ScaleFilterCols(rowptr, src, dst_width, x, dx);
132688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          rowptr += rowstride;
132788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          rowstride = -rowstride;
132888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          lasty = yi;
132988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          src += src_stride;
133088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        }
133188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
133288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      if (filtering == kFilterLinear) {
133388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0);
133488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      } else {
133588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        int yf = (y >> 8) & 255;
133688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf);
133788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      }
133888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_ptr += dst_stride;
133988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      y += dy;
134088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
134188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    free_aligned_buffer_64(row);
134288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
134388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
134488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
134588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale Plane to/from any dimensions, without interpolation.
134688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Fixed point math is used for performance: The upper 16 bits
134788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// of x and dx is the integer part of the source position and
134888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// the lower 16 bits are the fixed decimal part.
134988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
135088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneSimple(int src_width, int src_height,
135188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int dst_width, int dst_height,
135288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             int src_stride, int dst_stride,
135388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             const uint8* src_ptr, uint8* dst_ptr) {
135488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
135588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleCols)(uint8* dst_ptr, const uint8* src_ptr,
135688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int dst_width, int x, int dx) = ScaleCols_C;
135788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
135888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
135988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
136088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
136188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
136288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone,
136388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
136488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
136588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
136688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_width * 2 == dst_width && x < 0x8000) {
136788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleCols = ScaleColsUp2_C;
136888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALECOLS_SSE2)
136988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
137088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
137188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
137288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleCols = ScaleColsUp2_SSE2;
137388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
137488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
137588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
137688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
137788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_height; ++i) {
137888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleCols(dst_ptr, src_ptr + (y >> 16) * src_stride,
137988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              dst_width, x, dx);
138088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
138188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y += dy;
138288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
138388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
138488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
138588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgstatic void ScalePlaneSimple_16(int src_width, int src_height,
138688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                int dst_width, int dst_height,
138788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                int src_stride, int dst_stride,
138888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                const uint16* src_ptr, uint16* dst_ptr) {
138988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int i;
139088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  void (*ScaleCols)(uint16* dst_ptr, const uint16* src_ptr,
139188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      int dst_width, int x, int dx) = ScaleCols_16_C;
139288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Initial source x/y coordinate and step values as 16.16 fixed point.
139388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int x = 0;
139488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int y = 0;
139588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dx = 0;
139688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dy = 0;
139788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone,
139888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             &x, &y, &dx, &dy);
139988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  src_width = Abs(src_width);
140088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
140188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_width * 2 == dst_width && x < 0x8000) {
140288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleCols = ScaleColsUp2_16_C;
140388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#if defined(HAS_SCALECOLS_16_SSE2)
140488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
140588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
140688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
140788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScaleCols = ScaleColsUp2_16_SSE2;
140888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
140988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
141088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
141188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
141288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  for (i = 0; i < dst_height; ++i) {
141388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScaleCols(dst_ptr, src_ptr + (y >> 16) * src_stride,
141488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              dst_width, x, dx);
141588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    dst_ptr += dst_stride;
141688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    y += dy;
141788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
141888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
141988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
142088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale a plane.
142188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// This function dispatches to a specialized scaler based on scale factor.
142288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
142388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
142488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid ScalePlane(const uint8* src, int src_stride,
142588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                int src_width, int src_height,
142688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                uint8* dst, int dst_stride,
142788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                int dst_width, int dst_height,
142888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                enum FilterMode filtering) {
142988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Simplify filtering when possible.
143088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  filtering = ScaleFilterReduce(src_width, src_height,
143188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                dst_width, dst_height,
143288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                filtering);
143388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
143488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
143588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_height < 0) {
143688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_height = -src_height;
143788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src = src + (src_height - 1) * src_stride;
143888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = -src_stride;
143988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
144088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
144188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Use specialized scales to improve performance for common resolutions.
144288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // For example, all the 1/2 scalings will use ScalePlaneDown2()
144388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_width == src_width && dst_height == src_height) {
144488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Straight copy.
144588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyPlane(src, src_stride, dst, dst_stride, dst_width, dst_height);
144688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
144788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
144888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_width == src_width) {
144988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int dy = FixedDiv(src_height, dst_height);
145088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Arbitrary scale vertically, but unscaled vertically.
145188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneVertical(src_height,
145288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       dst_width, dst_height,
145388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       src_stride, dst_stride, src, dst,
145488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       0, 0, dy, 1, filtering);
145588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
145688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
145788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_width <= Abs(src_width) && dst_height <= src_height) {
145888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Scale down.
145988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (4 * dst_width == 3 * src_width &&
146088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        4 * dst_height == 3 * src_height) {
146188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 3/4
146288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown34(src_width, src_height, dst_width, dst_height,
146388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       src_stride, dst_stride, src, dst, filtering);
146488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
146588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
146688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (2 * dst_width == src_width && 2 * dst_height == src_height) {
146788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 1/2
146888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown2(src_width, src_height, dst_width, dst_height,
146988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      src_stride, dst_stride, src, dst, filtering);
147088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
147188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
147288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // 3/8 rounded up for odd sized chroma height.
147388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (8 * dst_width == 3 * src_width &&
147488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        dst_height == ((src_height * 3 + 7) / 8)) {
147588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 3/8
147688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown38(src_width, src_height, dst_width, dst_height,
147788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                       src_stride, dst_stride, src, dst, filtering);
147888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
147988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
148088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (4 * dst_width == src_width && 4 * dst_height == src_height &&
148188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               filtering != kFilterBilinear) {
148288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 1/4
148388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown4(src_width, src_height, dst_width, dst_height,
148488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      src_stride, dst_stride, src, dst, filtering);
148588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
148688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
148788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
148888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering == kFilterBox && dst_height * 2 < src_height) {
148988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneBox(src_width, src_height, dst_width, dst_height,
149088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  src_stride, dst_stride, src, dst);
149188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
149288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
149388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering && dst_height > src_height) {
149488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneBilinearUp(src_width, src_height, dst_width, dst_height,
149588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         src_stride, dst_stride, src, dst, filtering);
149688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
149788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
149888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering) {
149988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneBilinearDown(src_width, src_height, dst_width, dst_height,
150088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                           src_stride, dst_stride, src, dst, filtering);
150188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
150288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
150388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlaneSimple(src_width, src_height, dst_width, dst_height,
150488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_stride, dst_stride, src, dst);
150588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
150688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
150788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
150888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgvoid ScalePlane_16(const uint16* src, int src_stride,
150988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  int src_width, int src_height,
151088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  uint16* dst, int dst_stride,
151188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  int dst_width, int dst_height,
151288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                  enum FilterMode filtering) {
151388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Simplify filtering when possible.
151488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  filtering = ScaleFilterReduce(src_width, src_height,
151588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                dst_width, dst_height,
151688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                                filtering);
151788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
151888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Negative height means invert the image.
151988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (src_height < 0) {
152088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_height = -src_height;
152188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src = src + (src_height - 1) * src_stride;
152288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    src_stride = -src_stride;
152388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
152488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
152588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Use specialized scales to improve performance for common resolutions.
152688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // For example, all the 1/2 scalings will use ScalePlaneDown2()
152788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_width == src_width && dst_height == src_height) {
152888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Straight copy.
152988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    CopyPlane_16(src, src_stride, dst, dst_stride, dst_width, dst_height);
153088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
153188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
153288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_width == src_width) {
153388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    int dy = FixedDiv(src_height, dst_height);
153488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Arbitrary scale vertically, but unscaled vertically.
153588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneVertical_16(src_height,
153688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          dst_width, dst_height,
153788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          src_stride, dst_stride, src, dst,
153888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          0, 0, dy, 1, filtering);
153988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
154088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
154188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (dst_width <= Abs(src_width) && dst_height <= src_height) {
154288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // Scale down.
154388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (4 * dst_width == 3 * src_width &&
154488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        4 * dst_height == 3 * src_height) {
154588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 3/4
154688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown34_16(src_width, src_height, dst_width, dst_height,
154788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          src_stride, dst_stride, src, dst, filtering);
154888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
154988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
155088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (2 * dst_width == src_width && 2 * dst_height == src_height) {
155188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 1/2
155288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown2_16(src_width, src_height, dst_width, dst_height,
155388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         src_stride, dst_stride, src, dst, filtering);
155488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
155588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
155688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    // 3/8 rounded up for odd sized chroma height.
155788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (8 * dst_width == 3 * src_width &&
155888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org        dst_height == ((src_height * 3 + 7) / 8)) {
155988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 3/8
156088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown38_16(src_width, src_height, dst_width, dst_height,
156188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                          src_stride, dst_stride, src, dst, filtering);
156288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
156388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
156488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    if (4 * dst_width == src_width && 4 * dst_height == src_height &&
156588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org               filtering != kFilterBilinear) {
156688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      // optimized, 1/4
156788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      ScalePlaneDown4_16(src_width, src_height, dst_width, dst_height,
156888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                         src_stride, dst_stride, src, dst, filtering);
156988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      return;
157088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    }
157188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
157288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering == kFilterBox && dst_height * 2 < src_height) {
157388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneBox_16(src_width, src_height, dst_width, dst_height,
157488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                     src_stride, dst_stride, src, dst);
157588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
157688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
157788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering && dst_height > src_height) {
157888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneBilinearUp_16(src_width, src_height, dst_width, dst_height,
157988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                            src_stride, dst_stride, src, dst, filtering);
158088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
158188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
158288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (filtering) {
158388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    ScalePlaneBilinearDown_16(src_width, src_height, dst_width, dst_height,
158488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                              src_stride, dst_stride, src, dst, filtering);
158588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return;
158688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
158788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlaneSimple_16(src_width, src_height, dst_width, dst_height,
158888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                      src_stride, dst_stride, src, dst);
158988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
159088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
159188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Scale an I420 image.
159288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// This function in turn calls a scaling function for each plane.
159388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
159488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
159588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I420Scale(const uint8* src_y, int src_stride_y,
159688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              const uint8* src_u, int src_stride_u,
159788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              const uint8* src_v, int src_stride_v,
159888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int src_width, int src_height,
159988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint8* dst_y, int dst_stride_y,
160088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint8* dst_u, int dst_stride_u,
160188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              uint8* dst_v, int dst_stride_v,
160288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              int dst_width, int dst_height,
160388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org              enum FilterMode filtering) {
160488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
160588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int src_halfheight = SUBSAMPLE(src_height, 1, 1);
160688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
160788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
160888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 ||
160988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
161088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
161188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
161288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
161388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlane(src_y, src_stride_y, src_width, src_height,
161488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             dst_y, dst_stride_y, dst_width, dst_height,
161588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             filtering);
161688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight,
161788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             dst_u, dst_stride_u, dst_halfwidth, dst_halfheight,
161888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             filtering);
161988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight,
162088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             dst_v, dst_stride_v, dst_halfwidth, dst_halfheight,
162188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org             filtering);
162288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
162388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
162488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
162588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
162688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint I420Scale_16(const uint16* src_y, int src_stride_y,
162788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 const uint16* src_u, int src_stride_u,
162888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 const uint16* src_v, int src_stride_v,
162988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int src_width, int src_height,
163088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint16* dst_y, int dst_stride_y,
163188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint16* dst_u, int dst_stride_u,
163288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 uint16* dst_v, int dst_stride_v,
163388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 int dst_width, int dst_height,
163488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 enum FilterMode filtering) {
163588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
163688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int src_halfheight = SUBSAMPLE(src_height, 1, 1);
163788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
163888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
163988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 ||
164088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
164188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
164288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
164388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
164488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlane_16(src_y, src_stride_y, src_width, src_height,
164588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                dst_y, dst_stride_y, dst_width, dst_height,
164688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                filtering);
164788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlane_16(src_u, src_stride_u, src_halfwidth, src_halfheight,
164888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                dst_u, dst_stride_u, dst_halfwidth, dst_halfheight,
164988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                filtering);
165088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  ScalePlane_16(src_v, src_stride_v, src_halfwidth, src_halfheight,
165188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                dst_v, dst_stride_v, dst_halfwidth, dst_halfheight,
165288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                filtering);
165388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return 0;
165488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
165588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
165688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Deprecated api
165788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
165888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
165988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          int src_stride_y, int src_stride_u, int src_stride_v,
166088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          int src_width, int src_height,
166188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          uint8* dst_y, uint8* dst_u, uint8* dst_v,
166288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          int dst_stride_y, int dst_stride_u, int dst_stride_v,
166388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          int dst_width, int dst_height,
166488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org          LIBYUV_BOOL interpolate) {
166588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return I420Scale(src_y, src_stride_y,
166688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_u, src_stride_u,
166788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_v, src_stride_v,
166888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_width, src_height,
166988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_y, dst_stride_y,
167088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_u, dst_stride_u,
167188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_v, dst_stride_v,
167288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_width, dst_height,
167388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   interpolate ? kFilterBox : kFilterNone);
167488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
167588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
167688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org// Deprecated api
167788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgLIBYUV_API
167888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.orgint ScaleOffset(const uint8* src, int src_width, int src_height,
167988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                uint8* dst, int dst_width, int dst_height, int dst_yoffset,
168088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                LIBYUV_BOOL interpolate) {
168188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  // Chroma requires offset to multiple of 2.
168288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_yoffset_even = dst_yoffset & ~1;
168388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
168488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int src_halfheight = SUBSAMPLE(src_height, 1, 1);
168588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
168688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
168788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  int aheight = dst_height - dst_yoffset_even * 2;  // actual output height
168888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const uint8* src_y = src;
168988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const uint8* src_u = src + src_width * src_height;
169088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  const uint8* src_v = src + src_width * src_height +
169188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                             src_halfwidth * src_halfheight;
169288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst_y = dst + dst_yoffset_even * dst_width;
169388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst_u = dst + dst_width * dst_height +
169488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 (dst_yoffset_even >> 1) * dst_halfwidth;
169588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  uint8* dst_v = dst + dst_width * dst_height + dst_halfwidth * dst_halfheight +
169688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                 (dst_yoffset_even >> 1) * dst_halfwidth;
169788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  if (!src || src_width <= 0 || src_height <= 0 ||
169888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      !dst || dst_width <= 0 || dst_height <= 0 || dst_yoffset_even < 0 ||
169988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org      dst_yoffset_even >= dst_height) {
170088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org    return -1;
170188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  }
170288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  return I420Scale(src_y, src_width,
170388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_u, src_halfwidth,
170488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_v, src_halfwidth,
170588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   src_width, src_height,
170688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_y, dst_width,
170788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_u, dst_halfwidth,
170888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_v, dst_halfwidth,
170988b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   dst_width, aheight,
171088b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org                   interpolate ? kFilterBox : kFilterNone);
171188b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}
171288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org
171388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#ifdef __cplusplus
171488b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}  // extern "C"
171588b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org}  // namespace libyuv
171688b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org#endif
1717