xref: /aosp_15_r20/external/libaom/aom_dsp/blend_a64_mask.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h>
13*77c1e3ccSAndroid Build Coastguard Worker 
14*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_integer.h"
15*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/blend.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
18*77c1e3ccSAndroid Build Coastguard Worker 
19*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
20*77c1e3ccSAndroid Build Coastguard Worker 
21*77c1e3ccSAndroid Build Coastguard Worker // Blending with alpha mask. Mask values come from the range [0, 64],
22*77c1e3ccSAndroid Build Coastguard Worker // as described for AOM_BLEND_A64 in aom_dsp/blend.h. src0 or src1 can
23*77c1e3ccSAndroid Build Coastguard Worker // be the same as dst, or dst can be different from both sources.
24*77c1e3ccSAndroid Build Coastguard Worker 
25*77c1e3ccSAndroid Build Coastguard Worker // NOTE(rachelbarker): The input and output of aom_blend_a64_d16_mask_c() are
26*77c1e3ccSAndroid Build Coastguard Worker // in a higher intermediate precision, and will later be rounded down to pixel
27*77c1e3ccSAndroid Build Coastguard Worker // precision.
28*77c1e3ccSAndroid Build Coastguard Worker // Thus, in order to avoid double-rounding, we want to use normal right shifts
29*77c1e3ccSAndroid Build Coastguard Worker // within this function, not ROUND_POWER_OF_TWO.
30*77c1e3ccSAndroid Build Coastguard Worker // This works because of the identity:
31*77c1e3ccSAndroid Build Coastguard Worker // ROUND_POWER_OF_TWO(x >> y, z) == ROUND_POWER_OF_TWO(x, y+z)
32*77c1e3ccSAndroid Build Coastguard Worker //
33*77c1e3ccSAndroid Build Coastguard Worker // In contrast, the output of the non-d16 functions will not be further rounded,
34*77c1e3ccSAndroid Build Coastguard Worker // so we *should* use ROUND_POWER_OF_TWO there.
35*77c1e3ccSAndroid Build Coastguard Worker 
aom_lowbd_blend_a64_d16_mask_c(uint8_t * dst,uint32_t dst_stride,const CONV_BUF_TYPE * src0,uint32_t src0_stride,const CONV_BUF_TYPE * src1,uint32_t src1_stride,const uint8_t * mask,uint32_t mask_stride,int w,int h,int subw,int subh,ConvolveParams * conv_params)36*77c1e3ccSAndroid Build Coastguard Worker void aom_lowbd_blend_a64_d16_mask_c(
37*77c1e3ccSAndroid Build Coastguard Worker     uint8_t *dst, uint32_t dst_stride, const CONV_BUF_TYPE *src0,
38*77c1e3ccSAndroid Build Coastguard Worker     uint32_t src0_stride, const CONV_BUF_TYPE *src1, uint32_t src1_stride,
39*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *mask, uint32_t mask_stride, int w, int h, int subw, int subh,
40*77c1e3ccSAndroid Build Coastguard Worker     ConvolveParams *conv_params) {
41*77c1e3ccSAndroid Build Coastguard Worker   int i, j;
42*77c1e3ccSAndroid Build Coastguard Worker   const int bd = 8;
43*77c1e3ccSAndroid Build Coastguard Worker   const int offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
44*77c1e3ccSAndroid Build Coastguard Worker   const int round_offset = (1 << (offset_bits - conv_params->round_1)) +
45*77c1e3ccSAndroid Build Coastguard Worker                            (1 << (offset_bits - conv_params->round_1 - 1));
46*77c1e3ccSAndroid Build Coastguard Worker   const int round_bits =
47*77c1e3ccSAndroid Build Coastguard Worker       2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
48*77c1e3ccSAndroid Build Coastguard Worker 
49*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES((void *)src0 == dst, src0_stride == dst_stride));
50*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES((void *)src1 == dst, src1_stride == dst_stride));
51*77c1e3ccSAndroid Build Coastguard Worker 
52*77c1e3ccSAndroid Build Coastguard Worker   assert(h >= 4);
53*77c1e3ccSAndroid Build Coastguard Worker   assert(w >= 4);
54*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(h));
55*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(w));
56*77c1e3ccSAndroid Build Coastguard Worker 
57*77c1e3ccSAndroid Build Coastguard Worker   if (subw == 0 && subh == 0) {
58*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
59*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
60*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
61*77c1e3ccSAndroid Build Coastguard Worker         const int m = mask[i * mask_stride + j];
62*77c1e3ccSAndroid Build Coastguard Worker         res = ((m * (int32_t)src0[i * src0_stride + j] +
63*77c1e3ccSAndroid Build Coastguard Worker                 (AOM_BLEND_A64_MAX_ALPHA - m) *
64*77c1e3ccSAndroid Build Coastguard Worker                     (int32_t)src1[i * src1_stride + j]) >>
65*77c1e3ccSAndroid Build Coastguard Worker                AOM_BLEND_A64_ROUND_BITS);
66*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
67*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] =
68*77c1e3ccSAndroid Build Coastguard Worker             clip_pixel(ROUND_POWER_OF_TWO(res, round_bits));
69*77c1e3ccSAndroid Build Coastguard Worker       }
70*77c1e3ccSAndroid Build Coastguard Worker     }
71*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 1) {
72*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
73*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
74*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
75*77c1e3ccSAndroid Build Coastguard Worker         const int m = ROUND_POWER_OF_TWO(
76*77c1e3ccSAndroid Build Coastguard Worker             mask[(2 * i) * mask_stride + (2 * j)] +
77*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i + 1) * mask_stride + (2 * j)] +
78*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i) * mask_stride + (2 * j + 1)] +
79*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i + 1) * mask_stride + (2 * j + 1)],
80*77c1e3ccSAndroid Build Coastguard Worker             2);
81*77c1e3ccSAndroid Build Coastguard Worker         res = ((m * (int32_t)src0[i * src0_stride + j] +
82*77c1e3ccSAndroid Build Coastguard Worker                 (AOM_BLEND_A64_MAX_ALPHA - m) *
83*77c1e3ccSAndroid Build Coastguard Worker                     (int32_t)src1[i * src1_stride + j]) >>
84*77c1e3ccSAndroid Build Coastguard Worker                AOM_BLEND_A64_ROUND_BITS);
85*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
86*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] =
87*77c1e3ccSAndroid Build Coastguard Worker             clip_pixel(ROUND_POWER_OF_TWO(res, round_bits));
88*77c1e3ccSAndroid Build Coastguard Worker       }
89*77c1e3ccSAndroid Build Coastguard Worker     }
90*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 0) {
91*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
92*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
93*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
94*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[i * mask_stride + (2 * j)],
95*77c1e3ccSAndroid Build Coastguard Worker                                     mask[i * mask_stride + (2 * j + 1)]);
96*77c1e3ccSAndroid Build Coastguard Worker         res = ((m * (int32_t)src0[i * src0_stride + j] +
97*77c1e3ccSAndroid Build Coastguard Worker                 (AOM_BLEND_A64_MAX_ALPHA - m) *
98*77c1e3ccSAndroid Build Coastguard Worker                     (int32_t)src1[i * src1_stride + j]) >>
99*77c1e3ccSAndroid Build Coastguard Worker                AOM_BLEND_A64_ROUND_BITS);
100*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
101*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] =
102*77c1e3ccSAndroid Build Coastguard Worker             clip_pixel(ROUND_POWER_OF_TWO(res, round_bits));
103*77c1e3ccSAndroid Build Coastguard Worker       }
104*77c1e3ccSAndroid Build Coastguard Worker     }
105*77c1e3ccSAndroid Build Coastguard Worker   } else {
106*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
107*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
108*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
109*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[(2 * i) * mask_stride + j],
110*77c1e3ccSAndroid Build Coastguard Worker                                     mask[(2 * i + 1) * mask_stride + j]);
111*77c1e3ccSAndroid Build Coastguard Worker         res = ((int32_t)(m * (int32_t)src0[i * src0_stride + j] +
112*77c1e3ccSAndroid Build Coastguard Worker                          (AOM_BLEND_A64_MAX_ALPHA - m) *
113*77c1e3ccSAndroid Build Coastguard Worker                              (int32_t)src1[i * src1_stride + j]) >>
114*77c1e3ccSAndroid Build Coastguard Worker                AOM_BLEND_A64_ROUND_BITS);
115*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
116*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] =
117*77c1e3ccSAndroid Build Coastguard Worker             clip_pixel(ROUND_POWER_OF_TWO(res, round_bits));
118*77c1e3ccSAndroid Build Coastguard Worker       }
119*77c1e3ccSAndroid Build Coastguard Worker     }
120*77c1e3ccSAndroid Build Coastguard Worker   }
121*77c1e3ccSAndroid Build Coastguard Worker }
122*77c1e3ccSAndroid Build Coastguard Worker 
123*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
aom_highbd_blend_a64_d16_mask_c(uint8_t * dst_8,uint32_t dst_stride,const CONV_BUF_TYPE * src0,uint32_t src0_stride,const CONV_BUF_TYPE * src1,uint32_t src1_stride,const uint8_t * mask,uint32_t mask_stride,int w,int h,int subw,int subh,ConvolveParams * conv_params,const int bd)124*77c1e3ccSAndroid Build Coastguard Worker void aom_highbd_blend_a64_d16_mask_c(
125*77c1e3ccSAndroid Build Coastguard Worker     uint8_t *dst_8, uint32_t dst_stride, const CONV_BUF_TYPE *src0,
126*77c1e3ccSAndroid Build Coastguard Worker     uint32_t src0_stride, const CONV_BUF_TYPE *src1, uint32_t src1_stride,
127*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *mask, uint32_t mask_stride, int w, int h, int subw, int subh,
128*77c1e3ccSAndroid Build Coastguard Worker     ConvolveParams *conv_params, const int bd) {
129*77c1e3ccSAndroid Build Coastguard Worker   const int offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
130*77c1e3ccSAndroid Build Coastguard Worker   const int round_offset = (1 << (offset_bits - conv_params->round_1)) +
131*77c1e3ccSAndroid Build Coastguard Worker                            (1 << (offset_bits - conv_params->round_1 - 1));
132*77c1e3ccSAndroid Build Coastguard Worker   const int round_bits =
133*77c1e3ccSAndroid Build Coastguard Worker       2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
134*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst = CONVERT_TO_SHORTPTR(dst_8);
135*77c1e3ccSAndroid Build Coastguard Worker 
136*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
137*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
138*77c1e3ccSAndroid Build Coastguard Worker 
139*77c1e3ccSAndroid Build Coastguard Worker   assert(h >= 1);
140*77c1e3ccSAndroid Build Coastguard Worker   assert(w >= 1);
141*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(h));
142*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(w));
143*77c1e3ccSAndroid Build Coastguard Worker 
144*77c1e3ccSAndroid Build Coastguard Worker   // excerpt from clip_pixel_highbd()
145*77c1e3ccSAndroid Build Coastguard Worker   // set saturation_value to (1 << bd) - 1
146*77c1e3ccSAndroid Build Coastguard Worker   unsigned int saturation_value;
147*77c1e3ccSAndroid Build Coastguard Worker   switch (bd) {
148*77c1e3ccSAndroid Build Coastguard Worker     case 8:
149*77c1e3ccSAndroid Build Coastguard Worker     default: saturation_value = 255; break;
150*77c1e3ccSAndroid Build Coastguard Worker     case 10: saturation_value = 1023; break;
151*77c1e3ccSAndroid Build Coastguard Worker     case 12: saturation_value = 4095; break;
152*77c1e3ccSAndroid Build Coastguard Worker   }
153*77c1e3ccSAndroid Build Coastguard Worker 
154*77c1e3ccSAndroid Build Coastguard Worker   if (subw == 0 && subh == 0) {
155*77c1e3ccSAndroid Build Coastguard Worker     for (int i = 0; i < h; ++i) {
156*77c1e3ccSAndroid Build Coastguard Worker       for (int j = 0; j < w; ++j) {
157*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
158*77c1e3ccSAndroid Build Coastguard Worker         const int m = mask[j];
159*77c1e3ccSAndroid Build Coastguard Worker         res = ((m * src0[j] + (AOM_BLEND_A64_MAX_ALPHA - m) * src1[j]) >>
160*77c1e3ccSAndroid Build Coastguard Worker                AOM_BLEND_A64_ROUND_BITS);
161*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
162*77c1e3ccSAndroid Build Coastguard Worker         unsigned int v = negative_to_zero(ROUND_POWER_OF_TWO(res, round_bits));
163*77c1e3ccSAndroid Build Coastguard Worker         dst[j] = AOMMIN(v, saturation_value);
164*77c1e3ccSAndroid Build Coastguard Worker       }
165*77c1e3ccSAndroid Build Coastguard Worker       mask += mask_stride;
166*77c1e3ccSAndroid Build Coastguard Worker       src0 += src0_stride;
167*77c1e3ccSAndroid Build Coastguard Worker       src1 += src1_stride;
168*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
169*77c1e3ccSAndroid Build Coastguard Worker     }
170*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 1) {
171*77c1e3ccSAndroid Build Coastguard Worker     for (int i = 0; i < h; ++i) {
172*77c1e3ccSAndroid Build Coastguard Worker       for (int j = 0; j < w; ++j) {
173*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
174*77c1e3ccSAndroid Build Coastguard Worker         const int m = ROUND_POWER_OF_TWO(
175*77c1e3ccSAndroid Build Coastguard Worker             mask[2 * j] + mask[mask_stride + 2 * j] + mask[2 * j + 1] +
176*77c1e3ccSAndroid Build Coastguard Worker                 mask[mask_stride + 2 * j + 1],
177*77c1e3ccSAndroid Build Coastguard Worker             2);
178*77c1e3ccSAndroid Build Coastguard Worker         res = (m * src0[j] + (AOM_BLEND_A64_MAX_ALPHA - m) * src1[j]) >>
179*77c1e3ccSAndroid Build Coastguard Worker               AOM_BLEND_A64_ROUND_BITS;
180*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
181*77c1e3ccSAndroid Build Coastguard Worker         unsigned int v = negative_to_zero(ROUND_POWER_OF_TWO(res, round_bits));
182*77c1e3ccSAndroid Build Coastguard Worker         dst[j] = AOMMIN(v, saturation_value);
183*77c1e3ccSAndroid Build Coastguard Worker       }
184*77c1e3ccSAndroid Build Coastguard Worker       mask += 2 * mask_stride;
185*77c1e3ccSAndroid Build Coastguard Worker       src0 += src0_stride;
186*77c1e3ccSAndroid Build Coastguard Worker       src1 += src1_stride;
187*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
188*77c1e3ccSAndroid Build Coastguard Worker     }
189*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 0) {
190*77c1e3ccSAndroid Build Coastguard Worker     for (int i = 0; i < h; ++i) {
191*77c1e3ccSAndroid Build Coastguard Worker       for (int j = 0; j < w; ++j) {
192*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
193*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[2 * j], mask[2 * j + 1]);
194*77c1e3ccSAndroid Build Coastguard Worker         res = (m * src0[j] + (AOM_BLEND_A64_MAX_ALPHA - m) * src1[j]) >>
195*77c1e3ccSAndroid Build Coastguard Worker               AOM_BLEND_A64_ROUND_BITS;
196*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
197*77c1e3ccSAndroid Build Coastguard Worker         unsigned int v = negative_to_zero(ROUND_POWER_OF_TWO(res, round_bits));
198*77c1e3ccSAndroid Build Coastguard Worker         dst[j] = AOMMIN(v, saturation_value);
199*77c1e3ccSAndroid Build Coastguard Worker       }
200*77c1e3ccSAndroid Build Coastguard Worker       mask += mask_stride;
201*77c1e3ccSAndroid Build Coastguard Worker       src0 += src0_stride;
202*77c1e3ccSAndroid Build Coastguard Worker       src1 += src1_stride;
203*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
204*77c1e3ccSAndroid Build Coastguard Worker     }
205*77c1e3ccSAndroid Build Coastguard Worker   } else {
206*77c1e3ccSAndroid Build Coastguard Worker     for (int i = 0; i < h; ++i) {
207*77c1e3ccSAndroid Build Coastguard Worker       for (int j = 0; j < w; ++j) {
208*77c1e3ccSAndroid Build Coastguard Worker         int32_t res;
209*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[j], mask[mask_stride + j]);
210*77c1e3ccSAndroid Build Coastguard Worker         res = (m * src0[j] + (AOM_BLEND_A64_MAX_ALPHA - m) * src1[j]) >>
211*77c1e3ccSAndroid Build Coastguard Worker               AOM_BLEND_A64_ROUND_BITS;
212*77c1e3ccSAndroid Build Coastguard Worker         res -= round_offset;
213*77c1e3ccSAndroid Build Coastguard Worker         unsigned int v = negative_to_zero(ROUND_POWER_OF_TWO(res, round_bits));
214*77c1e3ccSAndroid Build Coastguard Worker         dst[j] = AOMMIN(v, saturation_value);
215*77c1e3ccSAndroid Build Coastguard Worker       }
216*77c1e3ccSAndroid Build Coastguard Worker       mask += 2 * mask_stride;
217*77c1e3ccSAndroid Build Coastguard Worker       src0 += src0_stride;
218*77c1e3ccSAndroid Build Coastguard Worker       src1 += src1_stride;
219*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
220*77c1e3ccSAndroid Build Coastguard Worker     }
221*77c1e3ccSAndroid Build Coastguard Worker   }
222*77c1e3ccSAndroid Build Coastguard Worker }
223*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
224*77c1e3ccSAndroid Build Coastguard Worker 
225*77c1e3ccSAndroid Build Coastguard Worker // Blending with alpha mask. Mask values come from the range [0, 64],
226*77c1e3ccSAndroid Build Coastguard Worker // as described for AOM_BLEND_A64 in aom_dsp/blend.h. src0 or src1 can
227*77c1e3ccSAndroid Build Coastguard Worker // be the same as dst, or dst can be different from both sources.
228*77c1e3ccSAndroid Build Coastguard Worker 
aom_blend_a64_mask_c(uint8_t * dst,uint32_t dst_stride,const uint8_t * src0,uint32_t src0_stride,const uint8_t * src1,uint32_t src1_stride,const uint8_t * mask,uint32_t mask_stride,int w,int h,int subw,int subh)229*77c1e3ccSAndroid Build Coastguard Worker void aom_blend_a64_mask_c(uint8_t *dst, uint32_t dst_stride,
230*77c1e3ccSAndroid Build Coastguard Worker                           const uint8_t *src0, uint32_t src0_stride,
231*77c1e3ccSAndroid Build Coastguard Worker                           const uint8_t *src1, uint32_t src1_stride,
232*77c1e3ccSAndroid Build Coastguard Worker                           const uint8_t *mask, uint32_t mask_stride, int w,
233*77c1e3ccSAndroid Build Coastguard Worker                           int h, int subw, int subh) {
234*77c1e3ccSAndroid Build Coastguard Worker   int i, j;
235*77c1e3ccSAndroid Build Coastguard Worker 
236*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
237*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
238*77c1e3ccSAndroid Build Coastguard Worker 
239*77c1e3ccSAndroid Build Coastguard Worker   assert(h >= 1);
240*77c1e3ccSAndroid Build Coastguard Worker   assert(w >= 1);
241*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(h));
242*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(w));
243*77c1e3ccSAndroid Build Coastguard Worker 
244*77c1e3ccSAndroid Build Coastguard Worker   if (subw == 0 && subh == 0) {
245*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
246*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
247*77c1e3ccSAndroid Build Coastguard Worker         const int m = mask[i * mask_stride + j];
248*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
249*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
250*77c1e3ccSAndroid Build Coastguard Worker       }
251*77c1e3ccSAndroid Build Coastguard Worker     }
252*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 1) {
253*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
254*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
255*77c1e3ccSAndroid Build Coastguard Worker         const int m = ROUND_POWER_OF_TWO(
256*77c1e3ccSAndroid Build Coastguard Worker             mask[(2 * i) * mask_stride + (2 * j)] +
257*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i + 1) * mask_stride + (2 * j)] +
258*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i) * mask_stride + (2 * j + 1)] +
259*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i + 1) * mask_stride + (2 * j + 1)],
260*77c1e3ccSAndroid Build Coastguard Worker             2);
261*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
262*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
263*77c1e3ccSAndroid Build Coastguard Worker       }
264*77c1e3ccSAndroid Build Coastguard Worker     }
265*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 0) {
266*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
267*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
268*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[i * mask_stride + (2 * j)],
269*77c1e3ccSAndroid Build Coastguard Worker                                     mask[i * mask_stride + (2 * j + 1)]);
270*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
271*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
272*77c1e3ccSAndroid Build Coastguard Worker       }
273*77c1e3ccSAndroid Build Coastguard Worker     }
274*77c1e3ccSAndroid Build Coastguard Worker   } else {
275*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
276*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
277*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[(2 * i) * mask_stride + j],
278*77c1e3ccSAndroid Build Coastguard Worker                                     mask[(2 * i + 1) * mask_stride + j]);
279*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
280*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
281*77c1e3ccSAndroid Build Coastguard Worker       }
282*77c1e3ccSAndroid Build Coastguard Worker     }
283*77c1e3ccSAndroid Build Coastguard Worker   }
284*77c1e3ccSAndroid Build Coastguard Worker }
285*77c1e3ccSAndroid Build Coastguard Worker 
286*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
aom_highbd_blend_a64_mask_c(uint8_t * dst_8,uint32_t dst_stride,const uint8_t * src0_8,uint32_t src0_stride,const uint8_t * src1_8,uint32_t src1_stride,const uint8_t * mask,uint32_t mask_stride,int w,int h,int subw,int subh,int bd)287*77c1e3ccSAndroid Build Coastguard Worker void aom_highbd_blend_a64_mask_c(uint8_t *dst_8, uint32_t dst_stride,
288*77c1e3ccSAndroid Build Coastguard Worker                                  const uint8_t *src0_8, uint32_t src0_stride,
289*77c1e3ccSAndroid Build Coastguard Worker                                  const uint8_t *src1_8, uint32_t src1_stride,
290*77c1e3ccSAndroid Build Coastguard Worker                                  const uint8_t *mask, uint32_t mask_stride,
291*77c1e3ccSAndroid Build Coastguard Worker                                  int w, int h, int subw, int subh, int bd) {
292*77c1e3ccSAndroid Build Coastguard Worker   int i, j;
293*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst = CONVERT_TO_SHORTPTR(dst_8);
294*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *src0 = CONVERT_TO_SHORTPTR(src0_8);
295*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *src1 = CONVERT_TO_SHORTPTR(src1_8);
296*77c1e3ccSAndroid Build Coastguard Worker   (void)bd;
297*77c1e3ccSAndroid Build Coastguard Worker 
298*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
299*77c1e3ccSAndroid Build Coastguard Worker   assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
300*77c1e3ccSAndroid Build Coastguard Worker 
301*77c1e3ccSAndroid Build Coastguard Worker   assert(h >= 1);
302*77c1e3ccSAndroid Build Coastguard Worker   assert(w >= 1);
303*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(h));
304*77c1e3ccSAndroid Build Coastguard Worker   assert(IS_POWER_OF_TWO(w));
305*77c1e3ccSAndroid Build Coastguard Worker 
306*77c1e3ccSAndroid Build Coastguard Worker   assert(bd == 8 || bd == 10 || bd == 12);
307*77c1e3ccSAndroid Build Coastguard Worker 
308*77c1e3ccSAndroid Build Coastguard Worker   if (subw == 0 && subh == 0) {
309*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
310*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
311*77c1e3ccSAndroid Build Coastguard Worker         const int m = mask[i * mask_stride + j];
312*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
313*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
314*77c1e3ccSAndroid Build Coastguard Worker       }
315*77c1e3ccSAndroid Build Coastguard Worker     }
316*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 1) {
317*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
318*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
319*77c1e3ccSAndroid Build Coastguard Worker         const int m = ROUND_POWER_OF_TWO(
320*77c1e3ccSAndroid Build Coastguard Worker             mask[(2 * i) * mask_stride + (2 * j)] +
321*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i + 1) * mask_stride + (2 * j)] +
322*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i) * mask_stride + (2 * j + 1)] +
323*77c1e3ccSAndroid Build Coastguard Worker                 mask[(2 * i + 1) * mask_stride + (2 * j + 1)],
324*77c1e3ccSAndroid Build Coastguard Worker             2);
325*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
326*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
327*77c1e3ccSAndroid Build Coastguard Worker       }
328*77c1e3ccSAndroid Build Coastguard Worker     }
329*77c1e3ccSAndroid Build Coastguard Worker   } else if (subw == 1 && subh == 0) {
330*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
331*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
332*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[i * mask_stride + (2 * j)],
333*77c1e3ccSAndroid Build Coastguard Worker                                     mask[i * mask_stride + (2 * j + 1)]);
334*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
335*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
336*77c1e3ccSAndroid Build Coastguard Worker       }
337*77c1e3ccSAndroid Build Coastguard Worker     }
338*77c1e3ccSAndroid Build Coastguard Worker   } else {
339*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < h; ++i) {
340*77c1e3ccSAndroid Build Coastguard Worker       for (j = 0; j < w; ++j) {
341*77c1e3ccSAndroid Build Coastguard Worker         const int m = AOM_BLEND_AVG(mask[(2 * i) * mask_stride + j],
342*77c1e3ccSAndroid Build Coastguard Worker                                     mask[(2 * i + 1) * mask_stride + j]);
343*77c1e3ccSAndroid Build Coastguard Worker         dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
344*77c1e3ccSAndroid Build Coastguard Worker                                                 src1[i * src1_stride + j]);
345*77c1e3ccSAndroid Build Coastguard Worker       }
346*77c1e3ccSAndroid Build Coastguard Worker     }
347*77c1e3ccSAndroid Build Coastguard Worker   }
348*77c1e3ccSAndroid Build Coastguard Worker }
349*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
350