| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include <arm_neon.h> | 11 #include <arm_neon.h> |
| 12 | 12 |
| 13 #include "./vp9_rtcd.h" | 13 #include "./vp9_rtcd.h" |
| 14 #include "./vpx_config.h" | 14 #include "./vpx_config.h" |
| 15 #include "vpx/vpx_integer.h" | 15 #include "vpx/vpx_integer.h" |
| 16 | 16 |
| 17 //------------------------------------------------------------------------------ | 17 //------------------------------------------------------------------------------ |
| 18 // DC 4x4 |
| 19 |
| 20 // 'do_above' and 'do_left' facilitate branch removal when inlined. |
| 21 static INLINE void dc_4x4(uint8_t *dst, ptrdiff_t stride, |
| 22 const uint8_t *above, const uint8_t *left, |
| 23 int do_above, int do_left) { |
| 24 uint16x8_t sum_top; |
| 25 uint16x8_t sum_left; |
| 26 uint8x8_t dc0; |
| 27 |
| 28 if (do_above) { |
| 29 const uint8x8_t A = vld1_u8(above); // top row |
| 30 const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top |
| 31 const uint16x4_t p1 = vpadd_u16(p0, p0); |
| 32 sum_top = vcombine_u16(p1, p1); |
| 33 } |
| 34 |
| 35 if (do_left) { |
| 36 const uint8x8_t L = vld1_u8(left); // left border |
| 37 const uint16x4_t p0 = vpaddl_u8(L); // cascading summation of the left |
| 38 const uint16x4_t p1 = vpadd_u16(p0, p0); |
| 39 sum_left = vcombine_u16(p1, p1); |
| 40 } |
| 41 |
| 42 if (do_above && do_left) { |
| 43 const uint16x8_t sum = vaddq_u16(sum_left, sum_top); |
| 44 dc0 = vrshrn_n_u16(sum, 3); |
| 45 } else if (do_above) { |
| 46 dc0 = vrshrn_n_u16(sum_top, 2); |
| 47 } else if (do_left) { |
| 48 dc0 = vrshrn_n_u16(sum_left, 2); |
| 49 } else { |
| 50 dc0 = vdup_n_u8(0x80); |
| 51 } |
| 52 |
| 53 { |
| 54 const uint8x8_t dc = vdup_lane_u8(dc0, 0); |
| 55 int i; |
| 56 for (i = 0; i < 4; ++i) { |
| 57 vst1_lane_u32((uint32_t*)(dst + i * stride), vreinterpret_u32_u8(dc), 0); |
| 58 } |
| 59 } |
| 60 } |
| 61 |
| 62 void vp9_dc_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 63 const uint8_t *above, const uint8_t *left) { |
| 64 dc_4x4(dst, stride, above, left, 1, 1); |
| 65 } |
| 66 |
| 67 void vp9_dc_left_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 68 const uint8_t *above, const uint8_t *left) { |
| 69 (void)above; |
| 70 dc_4x4(dst, stride, NULL, left, 0, 1); |
| 71 } |
| 72 |
| 73 void vp9_dc_top_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 74 const uint8_t *above, const uint8_t *left) { |
| 75 (void)left; |
| 76 dc_4x4(dst, stride, above, NULL, 1, 0); |
| 77 } |
| 78 |
| 79 void vp9_dc_128_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 80 const uint8_t *above, const uint8_t *left) { |
| 81 (void)above; |
| 82 (void)left; |
| 83 dc_4x4(dst, stride, NULL, NULL, 0, 0); |
| 84 } |
| 85 |
| 86 //------------------------------------------------------------------------------ |
| 18 // DC 8x8 | 87 // DC 8x8 |
| 19 | 88 |
| 20 // 'do_above' and 'do_left' facilitate branch removal when inlined. | 89 // 'do_above' and 'do_left' facilitate branch removal when inlined. |
| 21 static INLINE void dc_8x8(uint8_t *dst, ptrdiff_t stride, | 90 static INLINE void dc_8x8(uint8_t *dst, ptrdiff_t stride, |
| 22 const uint8_t *above, const uint8_t *left, | 91 const uint8_t *above, const uint8_t *left, |
| 23 int do_above, int do_left) { | 92 int do_above, int do_left) { |
| 24 uint16x8_t sum_top; | 93 uint16x8_t sum_top; |
| 25 uint16x8_t sum_left; | 94 uint16x8_t sum_left; |
| 26 uint8x8_t dc0; | 95 uint8x8_t dc0; |
| 27 | 96 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 } | 223 } |
| 155 | 224 |
| 156 void vp9_dc_128_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride, | 225 void vp9_dc_128_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride, |
| 157 const uint8_t *above, | 226 const uint8_t *above, |
| 158 const uint8_t *left) { | 227 const uint8_t *left) { |
| 159 (void)above; | 228 (void)above; |
| 160 (void)left; | 229 (void)left; |
| 161 dc_16x16(dst, stride, NULL, NULL, 0, 0); | 230 dc_16x16(dst, stride, NULL, NULL, 0, 0); |
| 162 } | 231 } |
| 163 | 232 |
| 233 //------------------------------------------------------------------------------ |
| 234 // DC 32x32 |
| 235 |
| 236 // 'do_above' and 'do_left' facilitate branch removal when inlined. |
| 237 static INLINE void dc_32x32(uint8_t *dst, ptrdiff_t stride, |
| 238 const uint8_t *above, const uint8_t *left, |
| 239 int do_above, int do_left) { |
| 240 uint16x8_t sum_top; |
| 241 uint16x8_t sum_left; |
| 242 uint8x8_t dc0; |
| 243 |
| 244 if (do_above) { |
| 245 const uint8x16_t A0 = vld1q_u8(above); // top row |
| 246 const uint8x16_t A1 = vld1q_u8(above + 16); |
| 247 const uint16x8_t p0 = vpaddlq_u8(A0); // cascading summation of the top |
| 248 const uint16x8_t p1 = vpaddlq_u8(A1); |
| 249 const uint16x8_t p2 = vaddq_u16(p0, p1); |
| 250 const uint16x4_t p3 = vadd_u16(vget_low_u16(p2), vget_high_u16(p2)); |
| 251 const uint16x4_t p4 = vpadd_u16(p3, p3); |
| 252 const uint16x4_t p5 = vpadd_u16(p4, p4); |
| 253 sum_top = vcombine_u16(p5, p5); |
| 254 } |
| 255 |
| 256 if (do_left) { |
| 257 const uint8x16_t L0 = vld1q_u8(left); // left row |
| 258 const uint8x16_t L1 = vld1q_u8(left + 16); |
| 259 const uint16x8_t p0 = vpaddlq_u8(L0); // cascading summation of the left |
| 260 const uint16x8_t p1 = vpaddlq_u8(L1); |
| 261 const uint16x8_t p2 = vaddq_u16(p0, p1); |
| 262 const uint16x4_t p3 = vadd_u16(vget_low_u16(p2), vget_high_u16(p2)); |
| 263 const uint16x4_t p4 = vpadd_u16(p3, p3); |
| 264 const uint16x4_t p5 = vpadd_u16(p4, p4); |
| 265 sum_left = vcombine_u16(p5, p5); |
| 266 } |
| 267 |
| 268 if (do_above && do_left) { |
| 269 const uint16x8_t sum = vaddq_u16(sum_left, sum_top); |
| 270 dc0 = vrshrn_n_u16(sum, 6); |
| 271 } else if (do_above) { |
| 272 dc0 = vrshrn_n_u16(sum_top, 5); |
| 273 } else if (do_left) { |
| 274 dc0 = vrshrn_n_u16(sum_left, 5); |
| 275 } else { |
| 276 dc0 = vdup_n_u8(0x80); |
| 277 } |
| 278 |
| 279 { |
| 280 const uint8x16_t dc = vdupq_lane_u8(dc0, 0); |
| 281 int i; |
| 282 for (i = 0; i < 32; ++i) { |
| 283 vst1q_u8(dst + i * stride, dc); |
| 284 vst1q_u8(dst + i * stride + 16, dc); |
| 285 } |
| 286 } |
| 287 } |
| 288 |
| 289 void vp9_dc_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride, |
| 290 const uint8_t *above, const uint8_t *left) { |
| 291 dc_32x32(dst, stride, above, left, 1, 1); |
| 292 } |
| 293 |
| 294 void vp9_dc_left_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride, |
| 295 const uint8_t *above, |
| 296 const uint8_t *left) { |
| 297 (void)above; |
| 298 dc_32x32(dst, stride, NULL, left, 0, 1); |
| 299 } |
| 300 |
| 301 void vp9_dc_top_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride, |
| 302 const uint8_t *above, |
| 303 const uint8_t *left) { |
| 304 (void)left; |
| 305 dc_32x32(dst, stride, above, NULL, 1, 0); |
| 306 } |
| 307 |
| 308 void vp9_dc_128_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride, |
| 309 const uint8_t *above, |
| 310 const uint8_t *left) { |
| 311 (void)above; |
| 312 (void)left; |
| 313 dc_32x32(dst, stride, NULL, NULL, 0, 0); |
| 314 } |
| 315 |
| 316 // ----------------------------------------------------------------------------- |
| 317 |
| 318 void vp9_d45_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 319 const uint8_t *above, const uint8_t *left) { |
| 320 const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(above)); // top row |
| 321 const uint64x1_t A1 = vshr_n_u64(A0, 8); |
| 322 const uint64x1_t A2 = vshr_n_u64(A0, 16); |
| 323 const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0); |
| 324 const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1); |
| 325 const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2); |
| 326 const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGH00); |
| 327 const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0); |
| 328 const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); |
| 329 const uint32x2_t r0 = vreinterpret_u32_u8(avg2); |
| 330 const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); |
| 331 const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); |
| 332 const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); |
| 333 (void)left; |
| 334 vst1_lane_u32((uint32_t *)(dst + 0 * stride), r0, 0); |
| 335 vst1_lane_u32((uint32_t *)(dst + 1 * stride), r1, 0); |
| 336 vst1_lane_u32((uint32_t *)(dst + 2 * stride), r2, 0); |
| 337 vst1_lane_u32((uint32_t *)(dst + 3 * stride), r3, 0); |
| 338 dst[3 * stride + 3] = above[7]; |
| 339 } |
| 340 |
| 341 void vp9_d45_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride, |
| 342 const uint8_t *above, const uint8_t *left) { |
| 343 static const uint8_t shuffle1[8] = { 1, 2, 3, 4, 5, 6, 7, 7 }; |
| 344 static const uint8_t shuffle2[8] = { 2, 3, 4, 5, 6, 7, 7, 7 }; |
| 345 const uint8x8_t sh_12345677 = vld1_u8(shuffle1); |
| 346 const uint8x8_t sh_23456777 = vld1_u8(shuffle2); |
| 347 const uint8x8_t A0 = vld1_u8(above); // top row |
| 348 const uint8x8_t A1 = vtbl1_u8(A0, sh_12345677); |
| 349 const uint8x8_t A2 = vtbl1_u8(A0, sh_23456777); |
| 350 const uint8x8_t avg1 = vhadd_u8(A0, A2); |
| 351 uint8x8_t row = vrhadd_u8(avg1, A1); |
| 352 int i; |
| 353 (void)left; |
| 354 for (i = 0; i < 7; ++i) { |
| 355 vst1_u8(dst + i * stride, row); |
| 356 row = vtbl1_u8(row, sh_12345677); |
| 357 } |
| 358 vst1_u8(dst + i * stride, row); |
| 359 } |
| 360 |
| 361 void vp9_d45_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride, |
| 362 const uint8_t *above, const uint8_t *left) { |
| 363 const uint8x16_t A0 = vld1q_u8(above); // top row |
| 364 const uint8x16_t above_right = vld1q_dup_u8(above + 15); |
| 365 const uint8x16_t A1 = vextq_u8(A0, above_right, 1); |
| 366 const uint8x16_t A2 = vextq_u8(A0, above_right, 2); |
| 367 const uint8x16_t avg1 = vhaddq_u8(A0, A2); |
| 368 uint8x16_t row = vrhaddq_u8(avg1, A1); |
| 369 int i; |
| 370 (void)left; |
| 371 for (i = 0; i < 15; ++i) { |
| 372 vst1q_u8(dst + i * stride, row); |
| 373 row = vextq_u8(row, above_right, 1); |
| 374 } |
| 375 vst1q_u8(dst + i * stride, row); |
| 376 } |
| 377 |
| 378 // ----------------------------------------------------------------------------- |
| 379 |
| 380 void vp9_d135_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 381 const uint8_t *above, const uint8_t *left) { |
| 382 const uint8x8_t XABCD_u8 = vld1_u8(above - 1); |
| 383 const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8); |
| 384 const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32); |
| 385 const uint32x2_t zero = vdup_n_u32(0); |
| 386 const uint32x2_t IJKL = vld1_lane_u32((const uint32_t *)left, zero, 0); |
| 387 const uint8x8_t IJKL_u8 = vreinterpret_u8_u32(IJKL); |
| 388 const uint64x1_t LKJI____ = vreinterpret_u64_u8(vrev32_u8(IJKL_u8)); |
| 389 const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC); |
| 390 const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8)); |
| 391 const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16)); |
| 392 const uint8_t D = vget_lane_u8(XABCD_u8, 4); |
| 393 const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6); |
| 394 const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC); |
| 395 const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8); |
| 396 const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_); |
| 397 const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); |
| 398 const uint32x2_t r3 = vreinterpret_u32_u8(avg2); |
| 399 const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); |
| 400 const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); |
| 401 const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); |
| 402 vst1_lane_u32((uint32_t *)(dst + 0 * stride), r0, 0); |
| 403 vst1_lane_u32((uint32_t *)(dst + 1 * stride), r1, 0); |
| 404 vst1_lane_u32((uint32_t *)(dst + 2 * stride), r2, 0); |
| 405 vst1_lane_u32((uint32_t *)(dst + 3 * stride), r3, 0); |
| 406 } |
| 407 |
| 164 #if !HAVE_NEON_ASM | 408 #if !HAVE_NEON_ASM |
| 165 | 409 |
| 166 void vp9_v_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, | 410 void vp9_v_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride, |
| 167 const uint8_t *above, const uint8_t *left) { | 411 const uint8_t *above, const uint8_t *left) { |
| 168 int i; | 412 int i; |
| 169 uint32x2_t d0u32 = vdup_n_u32(0); | 413 uint32x2_t d0u32 = vdup_n_u32(0); |
| 170 (void)left; | 414 (void)left; |
| 171 | 415 |
| 172 d0u32 = vld1_lane_u32((const uint32_t *)above, d0u32, 0); | 416 d0u32 = vld1_lane_u32((const uint32_t *)above, d0u32, 0); |
| 173 for (i = 0; i < 4; i++, dst += stride) | 417 for (i = 0; i < 4; i++, dst += stride) |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 d3u8 = vqmovun_s16(q15s16); | 813 d3u8 = vqmovun_s16(q15s16); |
| 570 q0u8 = vcombine_u8(d0u8, d1u8); | 814 q0u8 = vcombine_u8(d0u8, d1u8); |
| 571 q1u8 = vcombine_u8(d2u8, d3u8); | 815 q1u8 = vcombine_u8(d2u8, d3u8); |
| 572 vst1q_u64((uint64_t *)dst, vreinterpretq_u64_u8(q0u8)); | 816 vst1q_u64((uint64_t *)dst, vreinterpretq_u64_u8(q0u8)); |
| 573 vst1q_u64((uint64_t *)(dst + 16), vreinterpretq_u64_u8(q1u8)); | 817 vst1q_u64((uint64_t *)(dst + 16), vreinterpretq_u64_u8(q1u8)); |
| 574 dst += stride; | 818 dst += stride; |
| 575 } | 819 } |
| 576 } | 820 } |
| 577 } | 821 } |
| 578 #endif // !HAVE_NEON_ASM | 822 #endif // !HAVE_NEON_ASM |
| OLD | NEW |