1ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian/*
2ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *
4ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  in the file PATENTS. All contributing project authors may
8ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian */
10ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
11ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/scale.h"
12ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
13ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include <assert.h>
14ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include <string.h>
15ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
16ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/cpu_id.h"
17ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/planar_functions.h"  // For CopyARGB
18ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/row.h"
19ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/scale_row.h"
20ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
21ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
22ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramaniannamespace libyuv {
23ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianextern "C" {
24ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
25ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
26ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic __inline int Abs(int v) {
27ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return v >= 0 ? v : -v;
28ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
29ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
30ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ScaleARGB ARGB, 1/2
31ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// This is an optimized version for scaling down a ARGB to 1/2 of
32ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// its original size.
33ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGBDown2(int src_width, int src_height,
34ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int dst_width, int dst_height,
35ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int src_stride, int dst_stride,
36ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           const uint8* src_argb, uint8* dst_argb,
37ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int x, int dx, int y, int dy,
38ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           enum FilterMode filtering) {
39ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
40ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int row_stride = src_stride * (dy >> 16);
41ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride,
42ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            uint8* dst_argb, int dst_width) =
43ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    filtering == kFilterNone ? ScaleARGBRowDown2_C :
44ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_C :
45ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBRowDown2Box_C);
46ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert(dx == 65536 * 2);  // Test scale factor of 2.
47ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert((dy & 0x1ffff) == 0);  // Test vertical scale is multiple of 2.
48ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Advance to odd row, even column.
49ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering == kFilterBilinear) {
50ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += (y >> 16) * src_stride + (x >> 16) * 4;
51ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  } else {
52ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += (y >> 16) * src_stride + ((x >> 16) - 1) * 4;
53ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
54ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
55ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBROWDOWN2_SSE2)
56ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) &&
57ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(row_stride, 16) &&
58ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
59ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_SSE2 :
60ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_SSE2 :
61ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBRowDown2Box_SSE2);
62ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
63ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_SCALEARGBROWDOWN2_NEON)
64ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8) &&
65ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(row_stride, 4)) {
66ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2 = filtering ? ScaleARGBRowDown2Box_NEON :
67ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBRowDown2_NEON;
68ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
69ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
70ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
71ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering == kFilterLinear) {
72ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride = 0;
73ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
74ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (j = 0; j < dst_height; ++j) {
75ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2(src_argb, src_stride, dst_argb, dst_width);
76ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += row_stride;
77ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride;
78ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
79ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
80ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
81ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ScaleARGB ARGB, 1/4
82ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// This is an optimized version for scaling down a ARGB to 1/4 of
83ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// its original size.
84ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGBDown4Box(int src_width, int src_height,
85ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              int dst_width, int dst_height,
86ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              int src_stride, int dst_stride,
87ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              const uint8* src_argb, uint8* dst_argb,
88ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              int x, int dx, int y, int dy) {
89ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
90ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Allocate 2 rows of ARGB.
91ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int kRowSize = (dst_width * 2 * 4 + 15) & ~15;
92ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  align_buffer_64(row, kRowSize * 2);
93ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int row_stride = src_stride * (dy >> 16);
94ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride,
95ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* dst_argb, int dst_width) = ScaleARGBRowDown2Box_C;
96ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Advance to odd row, even column.
97ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  src_argb += (y >> 16) * src_stride + (x >> 16) * 4;
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert(dx == 65536 * 4);  // Test scale factor of 4.
99ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert((dy & 0x3ffff) == 0);  // Test vertical scale is multiple of 4.
100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBROWDOWN2_SSE2)
101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) &&
102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(row_stride, 16) &&
103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2 = ScaleARGBRowDown2Box_SSE2;
105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_SCALEARGBROWDOWN2_NEON)
107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8) &&
108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(row_stride, 4)) {
109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2 = ScaleARGBRowDown2Box_NEON;
110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (j = 0; j < dst_height; ++j) {
113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2(src_argb, src_stride, row, dst_width * 2);
114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2(src_argb + src_stride * 2, src_stride,
115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      row + kRowSize, dst_width * 2);
116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDown2(row, kRowSize, dst_argb, dst_width);
117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += row_stride;
118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride;
119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  free_aligned_buffer_64(row);
121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ScaleARGB ARGB Even
124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// This is an optimized version for scaling down a ARGB to even
125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// multiple of its original size.
126ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGBDownEven(int src_width, int src_height,
127ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              int dst_width, int dst_height,
128ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              int src_stride, int dst_stride,
129ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              const uint8* src_argb, uint8* dst_argb,
130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              int x, int dx, int y, int dy,
131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              enum FilterMode filtering) {
132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int col_step = dx >> 16;
134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int row_stride = (dy >> 16) * src_stride;
135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBRowDownEven)(const uint8* src_argb, ptrdiff_t src_stride,
136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                               int src_step, uint8* dst_argb, int dst_width) =
137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      filtering ? ScaleARGBRowDownEvenBox_C : ScaleARGBRowDownEven_C;
138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert(IS_ALIGNED(src_width, 2));
139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert(IS_ALIGNED(src_height, 2));
140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  src_argb += (y >> 16) * src_stride + (x >> 16) * 4;
141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2)
142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 4) &&
143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_SSE2 :
145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBRowDownEven_SSE2;
146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_SCALEARGBROWDOWNEVEN_NEON)
148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 4) &&
149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 4)) {
150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_NEON :
151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBRowDownEven_NEON;
152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering == kFilterLinear) {
156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride = 0;
157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (j = 0; j < dst_height; ++j) {
159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBRowDownEven(src_argb, src_stride, col_step, dst_argb, dst_width);
160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += row_stride;
161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride;
162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Scale ARGB down with bilinear interpolation.
166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGBBilinearDown(int src_width, int src_height,
167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                  int dst_width, int dst_height,
168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                  int src_stride, int dst_stride,
169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                  const uint8* src_argb, uint8* dst_argb,
170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                  int x, int dx, int y, int dy,
171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                  enum FilterMode filtering) {
172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow_C;
176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBFilterCols)(uint8* dst_argb, const uint8* src_argb,
177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int dst_width, int x, int dx) =
178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      (src_width >= 32768) ? ScaleARGBFilterCols64_C : ScaleARGBFilterCols_C;
179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int64 xlast = x + (int64)(dst_width - 1) * dx;
180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int64 xl = (dx >= 0) ? x : xlast;
181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int64 xr = (dx >= 0) ? xlast : x;
182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int clip_src_width;
183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  xl = (xl >> 16) & ~3;  // Left edge aligned.
184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  xr = (xr >> 16) + 1;  // Right most pixel used.  Bilinear uses 2 pixels.
185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  xr = (xr + 1 + 3) & ~3;  // 1 beyond 4 pixel aligned right most pixel.
186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (xr > src_width) {
187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    xr = src_width;
188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  clip_src_width = (int)(xr - xl) * 4;  // Width aligned to 4.
190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  src_argb += xl * 4;
191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  x -= (int)(xl << 16);
192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && clip_src_width >= 16) {
194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(clip_src_width, 16)) {
196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSE2;
197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16)) {
198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSE2;
199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && clip_src_width >= 16) {
205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(clip_src_width, 16)) {
207ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16)) {
209ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSSE3;
210ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
213ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && clip_src_width >= 32) {
216ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(clip_src_width, 32)) {
218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
221ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && clip_src_width >= 16) {
224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(clip_src_width, 16)) {
226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && clip_src_width >= 4 &&
232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4)) {
233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_MIPS_DSPR2;
234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(clip_src_width, 4)) {
235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_MIPS_DSPR2;
236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBFILTERCOLS_SSSE3)
240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3;
242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Allocate a row of ARGB.
246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  {
247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    align_buffer_64(row, clip_src_width * 4);
248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    const int max_y = (src_height - 1) << 16;
250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (y > max_y) {
251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      y = max_y;
252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (j = 0; j < dst_height; ++j) {
254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int yi = y >> 16;
255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src = src_argb + yi * src_stride;
256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (filtering == kFilterLinear) {
257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBFilterCols(dst_argb, src, dst_width, x, dx);
258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        int yf = (y >> 8) & 255;
260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow(row, src, src_stride, clip_src_width, yf);
261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBFilterCols(dst_argb, row, dst_width, x, dx);
262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_argb += dst_stride;
264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      y += dy;
265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (y > max_y) {
266ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        y = max_y;
267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    free_aligned_buffer_64(row);
270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Scale ARGB up with bilinear interpolation.
274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGBBilinearUp(int src_width, int src_height,
275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                int dst_width, int dst_height,
276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                int src_stride, int dst_stride,
277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                const uint8* src_argb, uint8* dst_argb,
278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                int x, int dx, int y, int dy,
279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                enum FilterMode filtering) {
280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow_C;
284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBFilterCols)(uint8* dst_argb, const uint8* src_argb,
285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int dst_width, int x, int dx) =
286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      filtering ? ScaleARGBFilterCols_C : ScaleARGBCols_C;
287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int max_y = (src_height - 1) << 16;
288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 4) {
290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 4)) {
292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSE2;
293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSE2;
295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 4) {
301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 4)) {
303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSSE3;
306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
310ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
311ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 8) {
312ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
313ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 8)) {
314ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
315ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
316ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && dst_width >= 4) {
320ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 4)) {
322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
324ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
327ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 1 &&
328ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
329ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_MIPS_DSPR2;
330ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
331ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
332ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_width >= 32768) {
333ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = filtering ?
334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBFilterCols64_C : ScaleARGBCols64_C;
335ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
336ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBFILTERCOLS_SSSE3)
337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
338ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3;
339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
341ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBCOLS_SSE2)
342ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!filtering && TestCpuFlag(kCpuHasSSE2) && src_width < 32768) {
343ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBCols_SSE2;
344ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
345ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
346ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
347ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBColsUp2_C;
348ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBCOLSUP2_SSE2)
349ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
350ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
351ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
352ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ScaleARGBFilterCols = ScaleARGBColsUp2_SSE2;
353ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
354ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
355ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
356ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
357ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (y > max_y) {
358ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    y = max_y;
359ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
360ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
361ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  {
362ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int yi = y >> 16;
363ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    const uint8* src = src_argb + yi * src_stride;
364ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
365ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Allocate 2 rows of ARGB.
366ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    const int kRowSize = (dst_width * 4 + 15) & ~15;
367ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    align_buffer_64(row, kRowSize * 2);
368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
369ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* rowptr = row;
370ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int rowstride = kRowSize;
371ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int lasty = yi;
372ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
373ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols(rowptr, src, dst_width, x, dx);
374ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (src_height > 1) {
375ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src += src_stride;
376ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols(rowptr + rowstride, src, dst_width, x, dx);
378ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src += src_stride;
379ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
380ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (j = 0; j < dst_height; ++j) {
381ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      yi = y >> 16;
382ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (yi != lasty) {
383ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (y > max_y) {
384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          y = max_y;
385ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          yi = y >> 16;
386ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          src = src_argb + yi * src_stride;
387ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
388ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (yi != lasty) {
389ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          ScaleARGBFilterCols(rowptr, src, dst_width, x, dx);
390ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          rowptr += rowstride;
391ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          rowstride = -rowstride;
392ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          lasty = yi;
393ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          src += src_stride;
394ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
395ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
396ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (filtering == kFilterLinear) {
397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow(dst_argb, rowptr, 0, dst_width * 4, 0);
398ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
399ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        int yf = (y >> 8) & 255;
400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow(dst_argb, rowptr, rowstride, dst_width * 4, yf);
401ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
402ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_argb += dst_stride;
403ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      y += dy;
404ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
405ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    free_aligned_buffer_64(row);
406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
407ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
408ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
409ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef YUVSCALEUP
410ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Scale YUV to ARGB up with bilinear interpolation.
411ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleYUVToARGBBilinearUp(int src_width, int src_height,
412ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     int dst_width, int dst_height,
413ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     int src_stride_y,
414ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     int src_stride_u,
415ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     int src_stride_v,
416ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     int dst_stride_argb,
417ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     const uint8* src_y,
418ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     const uint8* src_u,
419ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     const uint8* src_v,
420ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     uint8* dst_argb,
421ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     int x, int dx, int y, int dy,
422ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     enum FilterMode filtering) {
423ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
424ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToARGBRow)(const uint8* y_buf,
425ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
426ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
427ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
428ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToARGBRow_C;
429ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOARGBROW_SSSE3)
430ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 8) {
431ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(src_width, 8)) {
433ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3;
434ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
435ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        I422ToARGBRow = I422ToARGBRow_SSSE3;
436ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
437ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
438ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
439ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
440ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOARGBROW_AVX2)
441ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && src_width >= 16) {
442ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToARGBRow = I422ToARGBRow_Any_AVX2;
443ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(src_width, 16)) {
444ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToARGBRow = I422ToARGBRow_AVX2;
445ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
446ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
447ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
448ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOARGBROW_NEON)
449ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && src_width >= 8) {
450ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToARGBRow = I422ToARGBRow_Any_NEON;
451ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(src_width, 8)) {
452ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToARGBRow = I422ToARGBRow_NEON;
453ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
454ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
455ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
456ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOARGBROW_MIPS_DSPR2)
457ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(src_width, 4) &&
458ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
459ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
460ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
461ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
462ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2;
463ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
464ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
465ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
466ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow_C;
469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
470ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && dst_width >= 4) {
471ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 4)) {
473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSE2;
474ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSE2;
476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
477ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
478ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
480ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
481ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && dst_width >= 4) {
482ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
483ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 4)) {
484ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
485ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
486ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSSE3;
487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
489ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
491ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && dst_width >= 8) {
493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
494ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 8)) {
495ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
496ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
497ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
498ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
499ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
500ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && dst_width >= 4) {
501ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
502ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(dst_width, 4)) {
503ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
505ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
506ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
507ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
508ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width >= 1 &&
509ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
510ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_MIPS_DSPR2;
511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
512ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
513ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
514ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBFilterCols)(uint8* dst_argb, const uint8* src_argb,
515ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int dst_width, int x, int dx) =
516ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      filtering ? ScaleARGBFilterCols_C : ScaleARGBCols_C;
517ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_width >= 32768) {
518ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = filtering ?
519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBFilterCols64_C : ScaleARGBCols64_C;
520ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
521ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBFILTERCOLS_SSSE3)
522ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
523ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3;
524ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
525ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBCOLS_SSE2)
527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!filtering && TestCpuFlag(kCpuHasSSE2) && src_width < 32768) {
528ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBCols_SSE2;
529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
530ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
531ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
532ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterCols = ScaleARGBColsUp2_C;
533ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBCOLSUP2_SSE2)
534ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
535ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
536ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
537ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ScaleARGBFilterCols = ScaleARGBColsUp2_SSE2;
538ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
539ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
540ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
541ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int max_y = (src_height - 1) << 16;
543ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (y > max_y) {
544ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    y = max_y;
545ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
546ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int kYShift = 1;  // Shift Y by 1 to convert Y plane to UV coordinate.
547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int yi = y >> 16;
548ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int uv_yi = yi >> kYShift;
549ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8* src_row_y = src_y + yi * src_stride_y;
550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8* src_row_u = src_u + uv_yi * src_stride_u;
551ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8* src_row_v = src_v + uv_yi * src_stride_v;
552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Allocate 2 rows of ARGB.
554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int kRowSize = (dst_width * 4 + 15) & ~15;
555ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  align_buffer_64(row, kRowSize * 2);
556ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
557ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Allocate 1 row of ARGB for source conversion.
558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  align_buffer_64(argb_row, src_width * 4);
559ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
560ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* rowptr = row;
561ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int rowstride = kRowSize;
562ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int lasty = yi;
563ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
564ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // TODO(fbarchard): Convert first 2 rows of YUV to ARGB.
565ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ScaleARGBFilterCols(rowptr, src_row_y, dst_width, x, dx);
566ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_height > 1) {
567ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_row_y += src_stride_y;
568ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (yi & 1) {
569ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_row_u += src_stride_u;
570ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_row_v += src_stride_v;
571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
573ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ScaleARGBFilterCols(rowptr + rowstride, src_row_y, dst_width, x, dx);
574ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_height > 2) {
575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_row_y += src_stride_y;
576ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!(yi & 1)) {
577ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_row_u += src_stride_u;
578ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_row_v += src_stride_v;
579ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
580ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
581ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
582ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (j = 0; j < dst_height; ++j) {
583ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    yi = y >> 16;
584ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (yi != lasty) {
585ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (y > max_y) {
586ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        y = max_y;
587ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        yi = y >> 16;
588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        uv_yi = yi >> kYShift;
589ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_row_y = src_y + yi * src_stride_y;
590ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_row_u = src_u + uv_yi * src_stride_u;
591ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_row_v = src_v + uv_yi * src_stride_v;
592ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
593ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (yi != lasty) {
594ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        // TODO(fbarchard): Convert the clipped region of row.
595ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        I422ToARGBRow(src_row_y, src_row_u, src_row_v, argb_row, src_width);
596ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBFilterCols(rowptr, argb_row, dst_width, x, dx);
597ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        rowptr += rowstride;
598ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        rowstride = -rowstride;
599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        lasty = yi;
600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_row_y += src_stride_y;
601ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (yi & 1) {
602ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          src_row_u += src_stride_u;
603ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          src_row_v += src_stride_v;
604ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
605ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
606ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (filtering == kFilterLinear) {
608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow(dst_argb, rowptr, 0, dst_width * 4, 0);
609ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    } else {
610ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int yf = (y >> 8) & 255;
611ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow(dst_argb, rowptr, rowstride, dst_width * 4, yf);
612ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
613ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
614ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    y += dy;
615ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
616ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  free_aligned_buffer_64(row);
617ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  free_aligned_buffer_64(row_argb);
618ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
619ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
620ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
621ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Scale ARGB to/from any dimensions, without interpolation.
622ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Fixed point math is used for performance: The upper 16 bits
623ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// of x and dx is the integer part of the source position and
624ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// the lower 16 bits are the fixed decimal part.
625ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
626ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGBSimple(int src_width, int src_height,
627ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int dst_width, int dst_height,
628ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int src_stride, int dst_stride,
629ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            const uint8* src_argb, uint8* dst_argb,
630ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int x, int dx, int y, int dy) {
631ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int j;
632ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ScaleARGBCols)(uint8* dst_argb, const uint8* src_argb,
633ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int dst_width, int x, int dx) =
634ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      (src_width >= 32768) ? ScaleARGBCols64_C : ScaleARGBCols_C;
635ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBCOLS_SSE2)
636ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && src_width < 32768) {
637ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBCols = ScaleARGBCols_SSE2;
638ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
639ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
640ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_width * 2 == dst_width && x < 0x8000) {
641ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBCols = ScaleARGBColsUp2_C;
642ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SCALEARGBCOLSUP2_SSE2)
643ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8) &&
644ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
645ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
646ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ScaleARGBCols = ScaleARGBColsUp2_SSE2;
647ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
648ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
649ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
650ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
651ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (j = 0; j < dst_height; ++j) {
652ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBCols(dst_argb, src_argb + (y >> 16) * src_stride,
653ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  dst_width, x, dx);
654ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride;
655ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    y += dy;
656ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
657ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
658ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
659ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ScaleARGB a ARGB.
660ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// This function in turn calls a scaling function
661ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// suitable for handling the desired resolutions.
662ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void ScaleARGB(const uint8* src, int src_stride,
663ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int src_width, int src_height,
664ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      uint8* dst, int dst_stride,
665ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int dst_width, int dst_height,
666ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int clip_x, int clip_y, int clip_width, int clip_height,
667ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      enum FilterMode filtering) {
668ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Initial source x/y coordinate and step values as 16.16 fixed point.
669ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int x = 0;
670ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y = 0;
671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int dx = 0;
672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int dy = 0;
673ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // ARGB does not support box filter yet, but allow the user to pass it.
674ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Simplify filtering when possible.
675ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filtering = ScaleFilterReduce(src_width, src_height,
676ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                dst_width, dst_height,
677ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                filtering);
678ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
679ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative src_height means invert the image.
680ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_height < 0) {
681ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_height = -src_height;
682ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src = src + (src_height - 1) * src_stride;
683ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride = -src_stride;
684ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
685ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ScaleSlope(src_width, src_height, dst_width, dst_height, filtering,
686ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             &x, &y, &dx, &dy);
687ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  src_width = Abs(src_width);
688ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (clip_x) {
689ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int64 clipf = (int64)(clip_x) * dx;
690ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    x += (clipf & 0xffff);
691ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src += (clipf >> 16) * 4;
692ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += clip_x * 4;
693ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
694ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (clip_y) {
695ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int64 clipf = (int64)(clip_y) * dy;
696ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    y += (clipf & 0xffff);
697ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src += (clipf >> 16) * src_stride;
698ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += clip_y * dst_stride;
699ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
700ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
701ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Special case for integer step values.
702ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (((dx | dy) & 0xffff) == 0) {
703ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!dx || !dy) {  // 1 pixel wide and/or tall.
704ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      filtering = kFilterNone;
705ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    } else {
706ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      // Optimized even scale down. ie 2, 4, 6, 8, 10x.
707ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (!(dx & 0x10000) && !(dy & 0x10000)) {
708ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (dx == 0x20000) {
709ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          // Optimized 1/2 downsample.
710ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          ScaleARGBDown2(src_width, src_height,
711ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         clip_width, clip_height,
712ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         src_stride, dst_stride, src, dst,
713ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         x, dx, y, dy, filtering);
714ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          return;
715ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
716ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (dx == 0x40000 && filtering == kFilterBox) {
717ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          // Optimized 1/4 box downsample.
718ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          ScaleARGBDown4Box(src_width, src_height,
719ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            clip_width, clip_height,
720ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            src_stride, dst_stride, src, dst,
721ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            x, dx, y, dy);
722ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          return;
723ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
724ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ScaleARGBDownEven(src_width, src_height,
725ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          clip_width, clip_height,
726ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          src_stride, dst_stride, src, dst,
727ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          x, dx, y, dy, filtering);
728ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        return;
729ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
730ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      // Optimized odd scale down. ie 3, 5, 7, 9x.
731ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if ((dx & 0x10000) && (dy & 0x10000)) {
732ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        filtering = kFilterNone;
733ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (dx == 0x10000 && dy == 0x10000) {
734ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          // Straight copy.
735ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          ARGBCopy(src + (y >> 16) * src_stride + (x >> 16) * 4, src_stride,
736ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   dst, dst_stride, clip_width, clip_height);
737ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          return;
738ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
739ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
740ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
741ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
742ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dx == 0x10000 && (x & 0xffff) == 0) {
743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Arbitrary scale vertically, but unscaled vertically.
744ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScalePlaneVertical(src_height,
745ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       clip_width, clip_height,
746ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       src_stride, dst_stride, src, dst,
747ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       x, y, dy, 4, filtering);
748ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return;
749ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
750ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering && dy < 65536) {
751ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBBilinearUp(src_width, src_height,
752ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        clip_width, clip_height,
753ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        src_stride, dst_stride, src, dst,
754ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        x, dx, y, dy, filtering);
755ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return;
756ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
757ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (filtering) {
758ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBBilinearDown(src_width, src_height,
759ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          clip_width, clip_height,
760ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          src_stride, dst_stride, src, dst,
761ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          x, dx, y, dy, filtering);
762ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return;
763ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
764ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ScaleARGBSimple(src_width, src_height, clip_width, clip_height,
765ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  src_stride, dst_stride, src, dst,
766ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  x, dx, y, dy);
767ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
768ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
769ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
770ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBScaleClip(const uint8* src_argb, int src_stride_argb,
771ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int src_width, int src_height,
772ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint8* dst_argb, int dst_stride_argb,
773ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int dst_width, int dst_height,
774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int clip_x, int clip_y, int clip_width, int clip_height,
775ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  enum FilterMode filtering) {
776ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || src_width == 0 || src_height == 0 ||
777ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_argb || dst_width <= 0 || dst_height <= 0 ||
778ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      clip_x < 0 || clip_y < 0 ||
779ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      (clip_x + clip_width) > dst_width ||
780ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      (clip_y + clip_height) > dst_height) {
781ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
782ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
783ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ScaleARGB(src_argb, src_stride_argb, src_width, src_height,
784ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            dst_argb, dst_stride_argb, dst_width, dst_height,
785ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            clip_x, clip_y, clip_width, clip_height, filtering);
786ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
787ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
788ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
789ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Scale an ARGB image.
790ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
791ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBScale(const uint8* src_argb, int src_stride_argb,
792ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int src_width, int src_height,
793ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
794ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int dst_width, int dst_height,
795ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              enum FilterMode filtering) {
796ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || src_width == 0 || src_height == 0 ||
797ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_argb || dst_width <= 0 || dst_height <= 0) {
798ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
799ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
800ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ScaleARGB(src_argb, src_stride_argb, src_width, src_height,
801ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            dst_argb, dst_stride_argb, dst_width, dst_height,
802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            0, 0, dst_width, dst_height, filtering);
803ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
804ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
806ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
807ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // extern "C"
808ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // namespace libyuv
809ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
810