1 /* 2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <arm_neon.h> 12 13 #include "./vpx_dsp_rtcd.h" 14 15 static INLINE void mbloop_filter_neon( 16 uint8x8_t dblimit, // mblimit 17 uint8x8_t dlimit, // limit 18 uint8x8_t dthresh, // thresh 19 uint8x8_t d3u8, // p2 20 uint8x8_t d4u8, // p2 21 uint8x8_t d5u8, // p1 22 uint8x8_t d6u8, // p0 23 uint8x8_t d7u8, // q0 24 uint8x8_t d16u8, // q1 25 uint8x8_t d17u8, // q2 26 uint8x8_t d18u8, // q3 27 uint8x8_t *d0ru8, // p1 28 uint8x8_t *d1ru8, // p1 29 uint8x8_t *d2ru8, // p0 30 uint8x8_t *d3ru8, // q0 31 uint8x8_t *d4ru8, // q1 32 uint8x8_t *d5ru8) { // q1 33 uint32_t flat; 34 uint8x8_t d0u8, d1u8, d2u8, d19u8, d20u8, d21u8, d22u8, d23u8, d24u8; 35 uint8x8_t d25u8, d26u8, d27u8, d28u8, d29u8, d30u8, d31u8; 36 int16x8_t q15s16; 37 uint16x8_t q10u16, q14u16; 38 int8x8_t d21s8, d24s8, d25s8, d26s8, d28s8, d29s8, d30s8; 39 40 d19u8 = vabd_u8(d3u8, d4u8); 41 d20u8 = vabd_u8(d4u8, d5u8); 42 d21u8 = vabd_u8(d5u8, d6u8); 43 d22u8 = vabd_u8(d16u8, d7u8); 44 d23u8 = vabd_u8(d17u8, d16u8); 45 d24u8 = vabd_u8(d18u8, d17u8); 46 47 d19u8 = vmax_u8(d19u8, d20u8); 48 d20u8 = vmax_u8(d21u8, d22u8); 49 50 d25u8 = vabd_u8(d6u8, d4u8); 51 52 d23u8 = vmax_u8(d23u8, d24u8); 53 54 d26u8 = vabd_u8(d7u8, d17u8); 55 56 d19u8 = vmax_u8(d19u8, d20u8); 57 58 d24u8 = vabd_u8(d6u8, d7u8); 59 d27u8 = vabd_u8(d3u8, d6u8); 60 d28u8 = vabd_u8(d18u8, d7u8); 61 62 d19u8 = vmax_u8(d19u8, d23u8); 63 64 d23u8 = vabd_u8(d5u8, d16u8); 65 d24u8 = vqadd_u8(d24u8, d24u8); 66 67 68 d19u8 = vcge_u8(dlimit, d19u8); 69 70 71 d25u8 = vmax_u8(d25u8, d26u8); 72 d26u8 = vmax_u8(d27u8, d28u8); 73 74 d23u8 = vshr_n_u8(d23u8, 1); 75 76 d25u8 = vmax_u8(d25u8, d26u8); 77 78 d24u8 = vqadd_u8(d24u8, d23u8); 79 80 d20u8 = vmax_u8(d20u8, d25u8); 81 82 d23u8 = vdup_n_u8(1); 83 d24u8 = vcge_u8(dblimit, d24u8); 84 85 d21u8 = vcgt_u8(d21u8, dthresh); 86 87 d20u8 = vcge_u8(d23u8, d20u8); 88 89 d19u8 = vand_u8(d19u8, d24u8); 90 91 d23u8 = vcgt_u8(d22u8, dthresh); 92 93 d20u8 = vand_u8(d20u8, d19u8); 94 95 d22u8 = vdup_n_u8(0x80); 96 97 d23u8 = vorr_u8(d21u8, d23u8); 98 99 q10u16 = vcombine_u16(vreinterpret_u16_u8(d20u8), 100 vreinterpret_u16_u8(d21u8)); 101 102 d30u8 = vshrn_n_u16(q10u16, 4); 103 flat = vget_lane_u32(vreinterpret_u32_u8(d30u8), 0); 104 105 if (flat == 0xffffffff) { // Check for all 1's, power_branch_only 106 d27u8 = vdup_n_u8(3); 107 d21u8 = vdup_n_u8(2); 108 q14u16 = vaddl_u8(d6u8, d7u8); 109 q14u16 = vmlal_u8(q14u16, d3u8, d27u8); 110 q14u16 = vmlal_u8(q14u16, d4u8, d21u8); 111 q14u16 = vaddw_u8(q14u16, d5u8); 112 *d0ru8 = vqrshrn_n_u16(q14u16, 3); 113 114 q14u16 = vsubw_u8(q14u16, d3u8); 115 q14u16 = vsubw_u8(q14u16, d4u8); 116 q14u16 = vaddw_u8(q14u16, d5u8); 117 q14u16 = vaddw_u8(q14u16, d16u8); 118 *d1ru8 = vqrshrn_n_u16(q14u16, 3); 119 120 q14u16 = vsubw_u8(q14u16, d3u8); 121 q14u16 = vsubw_u8(q14u16, d5u8); 122 q14u16 = vaddw_u8(q14u16, d6u8); 123 q14u16 = vaddw_u8(q14u16, d17u8); 124 *d2ru8 = vqrshrn_n_u16(q14u16, 3); 125 126 q14u16 = vsubw_u8(q14u16, d3u8); 127 q14u16 = vsubw_u8(q14u16, d6u8); 128 q14u16 = vaddw_u8(q14u16, d7u8); 129 q14u16 = vaddw_u8(q14u16, d18u8); 130 *d3ru8 = vqrshrn_n_u16(q14u16, 3); 131 132 q14u16 = vsubw_u8(q14u16, d4u8); 133 q14u16 = vsubw_u8(q14u16, d7u8); 134 q14u16 = vaddw_u8(q14u16, d16u8); 135 q14u16 = vaddw_u8(q14u16, d18u8); 136 *d4ru8 = vqrshrn_n_u16(q14u16, 3); 137 138 q14u16 = vsubw_u8(q14u16, d5u8); 139 q14u16 = vsubw_u8(q14u16, d16u8); 140 q14u16 = vaddw_u8(q14u16, d17u8); 141 q14u16 = vaddw_u8(q14u16, d18u8); 142 *d5ru8 = vqrshrn_n_u16(q14u16, 3); 143 } else { 144 d21u8 = veor_u8(d7u8, d22u8); 145 d24u8 = veor_u8(d6u8, d22u8); 146 d25u8 = veor_u8(d5u8, d22u8); 147 d26u8 = veor_u8(d16u8, d22u8); 148 149 d27u8 = vdup_n_u8(3); 150 151 d28s8 = vsub_s8(vreinterpret_s8_u8(d21u8), vreinterpret_s8_u8(d24u8)); 152 d29s8 = vqsub_s8(vreinterpret_s8_u8(d25u8), vreinterpret_s8_u8(d26u8)); 153 154 q15s16 = vmull_s8(d28s8, vreinterpret_s8_u8(d27u8)); 155 156 d29s8 = vand_s8(d29s8, vreinterpret_s8_u8(d23u8)); 157 158 q15s16 = vaddw_s8(q15s16, d29s8); 159 160 d29u8 = vdup_n_u8(4); 161 162 d28s8 = vqmovn_s16(q15s16); 163 164 d28s8 = vand_s8(d28s8, vreinterpret_s8_u8(d19u8)); 165 166 d30s8 = vqadd_s8(d28s8, vreinterpret_s8_u8(d27u8)); 167 d29s8 = vqadd_s8(d28s8, vreinterpret_s8_u8(d29u8)); 168 d30s8 = vshr_n_s8(d30s8, 3); 169 d29s8 = vshr_n_s8(d29s8, 3); 170 171 d24s8 = vqadd_s8(vreinterpret_s8_u8(d24u8), d30s8); 172 d21s8 = vqsub_s8(vreinterpret_s8_u8(d21u8), d29s8); 173 174 d29s8 = vrshr_n_s8(d29s8, 1); 175 d29s8 = vbic_s8(d29s8, vreinterpret_s8_u8(d23u8)); 176 177 d25s8 = vqadd_s8(vreinterpret_s8_u8(d25u8), d29s8); 178 d26s8 = vqsub_s8(vreinterpret_s8_u8(d26u8), d29s8); 179 180 if (flat == 0) { // filter_branch_only 181 *d0ru8 = d4u8; 182 *d1ru8 = veor_u8(vreinterpret_u8_s8(d25s8), d22u8); 183 *d2ru8 = veor_u8(vreinterpret_u8_s8(d24s8), d22u8); 184 *d3ru8 = veor_u8(vreinterpret_u8_s8(d21s8), d22u8); 185 *d4ru8 = veor_u8(vreinterpret_u8_s8(d26s8), d22u8); 186 *d5ru8 = d17u8; 187 return; 188 } 189 190 d21u8 = veor_u8(vreinterpret_u8_s8(d21s8), d22u8); 191 d24u8 = veor_u8(vreinterpret_u8_s8(d24s8), d22u8); 192 d25u8 = veor_u8(vreinterpret_u8_s8(d25s8), d22u8); 193 d26u8 = veor_u8(vreinterpret_u8_s8(d26s8), d22u8); 194 195 d23u8 = vdup_n_u8(2); 196 q14u16 = vaddl_u8(d6u8, d7u8); 197 q14u16 = vmlal_u8(q14u16, d3u8, d27u8); 198 q14u16 = vmlal_u8(q14u16, d4u8, d23u8); 199 200 d0u8 = vbsl_u8(d20u8, dblimit, d4u8); 201 202 q14u16 = vaddw_u8(q14u16, d5u8); 203 204 d1u8 = vbsl_u8(d20u8, dlimit, d25u8); 205 206 d30u8 = vqrshrn_n_u16(q14u16, 3); 207 208 q14u16 = vsubw_u8(q14u16, d3u8); 209 q14u16 = vsubw_u8(q14u16, d4u8); 210 q14u16 = vaddw_u8(q14u16, d5u8); 211 q14u16 = vaddw_u8(q14u16, d16u8); 212 213 d2u8 = vbsl_u8(d20u8, dthresh, d24u8); 214 215 d31u8 = vqrshrn_n_u16(q14u16, 3); 216 217 q14u16 = vsubw_u8(q14u16, d3u8); 218 q14u16 = vsubw_u8(q14u16, d5u8); 219 q14u16 = vaddw_u8(q14u16, d6u8); 220 q14u16 = vaddw_u8(q14u16, d17u8); 221 222 *d0ru8 = vbsl_u8(d20u8, d30u8, d0u8); 223 224 d23u8 = vqrshrn_n_u16(q14u16, 3); 225 226 q14u16 = vsubw_u8(q14u16, d3u8); 227 q14u16 = vsubw_u8(q14u16, d6u8); 228 q14u16 = vaddw_u8(q14u16, d7u8); 229 230 *d1ru8 = vbsl_u8(d20u8, d31u8, d1u8); 231 232 q14u16 = vaddw_u8(q14u16, d18u8); 233 234 *d2ru8 = vbsl_u8(d20u8, d23u8, d2u8); 235 236 d22u8 = vqrshrn_n_u16(q14u16, 3); 237 238 q14u16 = vsubw_u8(q14u16, d4u8); 239 q14u16 = vsubw_u8(q14u16, d7u8); 240 q14u16 = vaddw_u8(q14u16, d16u8); 241 242 d3u8 = vbsl_u8(d20u8, d3u8, d21u8); 243 244 q14u16 = vaddw_u8(q14u16, d18u8); 245 246 d4u8 = vbsl_u8(d20u8, d4u8, d26u8); 247 248 d6u8 = vqrshrn_n_u16(q14u16, 3); 249 250 q14u16 = vsubw_u8(q14u16, d5u8); 251 q14u16 = vsubw_u8(q14u16, d16u8); 252 q14u16 = vaddw_u8(q14u16, d17u8); 253 q14u16 = vaddw_u8(q14u16, d18u8); 254 255 d5u8 = vbsl_u8(d20u8, d5u8, d17u8); 256 257 d7u8 = vqrshrn_n_u16(q14u16, 3); 258 259 *d3ru8 = vbsl_u8(d20u8, d22u8, d3u8); 260 *d4ru8 = vbsl_u8(d20u8, d6u8, d4u8); 261 *d5ru8 = vbsl_u8(d20u8, d7u8, d5u8); 262 } 263 return; 264 } 265 266 void vpx_lpf_horizontal_8_neon( 267 uint8_t *src, 268 int pitch, 269 const uint8_t *blimit, 270 const uint8_t *limit, 271 const uint8_t *thresh, 272 int count) { 273 int i; 274 uint8_t *s, *psrc; 275 uint8x8_t dblimit, dlimit, dthresh; 276 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8; 277 uint8x8_t d16u8, d17u8, d18u8; 278 279 if (count == 0) // end_vpx_mblf_h_edge 280 return; 281 282 dblimit = vld1_u8(blimit); 283 dlimit = vld1_u8(limit); 284 dthresh = vld1_u8(thresh); 285 286 psrc = src - (pitch << 2); 287 for (i = 0; i < count; i++) { 288 s = psrc + i * 8; 289 290 d3u8 = vld1_u8(s); 291 s += pitch; 292 d4u8 = vld1_u8(s); 293 s += pitch; 294 d5u8 = vld1_u8(s); 295 s += pitch; 296 d6u8 = vld1_u8(s); 297 s += pitch; 298 d7u8 = vld1_u8(s); 299 s += pitch; 300 d16u8 = vld1_u8(s); 301 s += pitch; 302 d17u8 = vld1_u8(s); 303 s += pitch; 304 d18u8 = vld1_u8(s); 305 306 mbloop_filter_neon(dblimit, dlimit, dthresh, 307 d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8, 308 &d0u8, &d1u8, &d2u8, &d3u8, &d4u8, &d5u8); 309 310 s -= (pitch * 6); 311 vst1_u8(s, d0u8); 312 s += pitch; 313 vst1_u8(s, d1u8); 314 s += pitch; 315 vst1_u8(s, d2u8); 316 s += pitch; 317 vst1_u8(s, d3u8); 318 s += pitch; 319 vst1_u8(s, d4u8); 320 s += pitch; 321 vst1_u8(s, d5u8); 322 } 323 return; 324 } 325 326 void vpx_lpf_vertical_8_neon( 327 uint8_t *src, 328 int pitch, 329 const uint8_t *blimit, 330 const uint8_t *limit, 331 const uint8_t *thresh, 332 int count) { 333 int i; 334 uint8_t *s; 335 uint8x8_t dblimit, dlimit, dthresh; 336 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8; 337 uint8x8_t d16u8, d17u8, d18u8; 338 uint32x2x2_t d2tmp0, d2tmp1, d2tmp2, d2tmp3; 339 uint16x4x2_t d2tmp4, d2tmp5, d2tmp6, d2tmp7; 340 uint8x8x2_t d2tmp8, d2tmp9, d2tmp10, d2tmp11; 341 uint8x8x4_t d4Result; 342 uint8x8x2_t d2Result; 343 344 if (count == 0) 345 return; 346 347 dblimit = vld1_u8(blimit); 348 dlimit = vld1_u8(limit); 349 dthresh = vld1_u8(thresh); 350 351 for (i = 0; i < count; i++) { 352 s = src + (i * (pitch << 3)) - 4; 353 354 d3u8 = vld1_u8(s); 355 s += pitch; 356 d4u8 = vld1_u8(s); 357 s += pitch; 358 d5u8 = vld1_u8(s); 359 s += pitch; 360 d6u8 = vld1_u8(s); 361 s += pitch; 362 d7u8 = vld1_u8(s); 363 s += pitch; 364 d16u8 = vld1_u8(s); 365 s += pitch; 366 d17u8 = vld1_u8(s); 367 s += pitch; 368 d18u8 = vld1_u8(s); 369 370 d2tmp0 = vtrn_u32(vreinterpret_u32_u8(d3u8), 371 vreinterpret_u32_u8(d7u8)); 372 d2tmp1 = vtrn_u32(vreinterpret_u32_u8(d4u8), 373 vreinterpret_u32_u8(d16u8)); 374 d2tmp2 = vtrn_u32(vreinterpret_u32_u8(d5u8), 375 vreinterpret_u32_u8(d17u8)); 376 d2tmp3 = vtrn_u32(vreinterpret_u32_u8(d6u8), 377 vreinterpret_u32_u8(d18u8)); 378 379 d2tmp4 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[0]), 380 vreinterpret_u16_u32(d2tmp2.val[0])); 381 d2tmp5 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[0]), 382 vreinterpret_u16_u32(d2tmp3.val[0])); 383 d2tmp6 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[1]), 384 vreinterpret_u16_u32(d2tmp2.val[1])); 385 d2tmp7 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[1]), 386 vreinterpret_u16_u32(d2tmp3.val[1])); 387 388 d2tmp8 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[0]), 389 vreinterpret_u8_u16(d2tmp5.val[0])); 390 d2tmp9 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[1]), 391 vreinterpret_u8_u16(d2tmp5.val[1])); 392 d2tmp10 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[0]), 393 vreinterpret_u8_u16(d2tmp7.val[0])); 394 d2tmp11 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[1]), 395 vreinterpret_u8_u16(d2tmp7.val[1])); 396 397 d3u8 = d2tmp8.val[0]; 398 d4u8 = d2tmp8.val[1]; 399 d5u8 = d2tmp9.val[0]; 400 d6u8 = d2tmp9.val[1]; 401 d7u8 = d2tmp10.val[0]; 402 d16u8 = d2tmp10.val[1]; 403 d17u8 = d2tmp11.val[0]; 404 d18u8 = d2tmp11.val[1]; 405 406 mbloop_filter_neon(dblimit, dlimit, dthresh, 407 d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8, 408 &d0u8, &d1u8, &d2u8, &d3u8, &d4u8, &d5u8); 409 410 d4Result.val[0] = d0u8; 411 d4Result.val[1] = d1u8; 412 d4Result.val[2] = d2u8; 413 d4Result.val[3] = d3u8; 414 415 d2Result.val[0] = d4u8; 416 d2Result.val[1] = d5u8; 417 418 s = src - 3; 419 vst4_lane_u8(s, d4Result, 0); 420 s += pitch; 421 vst4_lane_u8(s, d4Result, 1); 422 s += pitch; 423 vst4_lane_u8(s, d4Result, 2); 424 s += pitch; 425 vst4_lane_u8(s, d4Result, 3); 426 s += pitch; 427 vst4_lane_u8(s, d4Result, 4); 428 s += pitch; 429 vst4_lane_u8(s, d4Result, 5); 430 s += pitch; 431 vst4_lane_u8(s, d4Result, 6); 432 s += pitch; 433 vst4_lane_u8(s, d4Result, 7); 434 435 s = src + 1; 436 vst2_lane_u8(s, d2Result, 0); 437 s += pitch; 438 vst2_lane_u8(s, d2Result, 1); 439 s += pitch; 440 vst2_lane_u8(s, d2Result, 2); 441 s += pitch; 442 vst2_lane_u8(s, d2Result, 3); 443 s += pitch; 444 vst2_lane_u8(s, d2Result, 4); 445 s += pitch; 446 vst2_lane_u8(s, d2Result, 5); 447 s += pitch; 448 vst2_lane_u8(s, d2Result, 6); 449 s += pitch; 450 vst2_lane_u8(s, d2Result, 7); 451 } 452 return; 453 } 454