vpx_convolve_avg_neon.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. #include <arm_neon.h>
  11. #include "./vpx_dsp_rtcd.h"
  12. #include "vpx/vpx_integer.h"
  13. void vpx_convolve_avg_neon(
  14. const uint8_t *src, // r0
  15. ptrdiff_t src_stride, // r1
  16. uint8_t *dst, // r2
  17. ptrdiff_t dst_stride, // r3
  18. const int16_t *filter_x,
  19. int filter_x_stride,
  20. const int16_t *filter_y,
  21. int filter_y_stride,
  22. int w,
  23. int h) {
  24. uint8_t *d;
  25. uint8x8_t d0u8, d1u8, d2u8, d3u8;
  26. uint32x2_t d0u32, d2u32;
  27. uint8x16_t q0u8, q1u8, q2u8, q3u8, q8u8, q9u8, q10u8, q11u8;
  28. (void)filter_x; (void)filter_x_stride;
  29. (void)filter_y; (void)filter_y_stride;
  30. d = dst;
  31. if (w > 32) { // avg64
  32. for (; h > 0; h -= 1) {
  33. q0u8 = vld1q_u8(src);
  34. q1u8 = vld1q_u8(src + 16);
  35. q2u8 = vld1q_u8(src + 32);
  36. q3u8 = vld1q_u8(src + 48);
  37. src += src_stride;
  38. q8u8 = vld1q_u8(d);
  39. q9u8 = vld1q_u8(d + 16);
  40. q10u8 = vld1q_u8(d + 32);
  41. q11u8 = vld1q_u8(d + 48);
  42. d += dst_stride;
  43. q0u8 = vrhaddq_u8(q0u8, q8u8);
  44. q1u8 = vrhaddq_u8(q1u8, q9u8);
  45. q2u8 = vrhaddq_u8(q2u8, q10u8);
  46. q3u8 = vrhaddq_u8(q3u8, q11u8);
  47. vst1q_u8(dst, q0u8);
  48. vst1q_u8(dst + 16, q1u8);
  49. vst1q_u8(dst + 32, q2u8);
  50. vst1q_u8(dst + 48, q3u8);
  51. dst += dst_stride;
  52. }
  53. } else if (w == 32) { // avg32
  54. for (; h > 0; h -= 2) {
  55. q0u8 = vld1q_u8(src);
  56. q1u8 = vld1q_u8(src + 16);
  57. src += src_stride;
  58. q2u8 = vld1q_u8(src);
  59. q3u8 = vld1q_u8(src + 16);
  60. src += src_stride;
  61. q8u8 = vld1q_u8(d);
  62. q9u8 = vld1q_u8(d + 16);
  63. d += dst_stride;
  64. q10u8 = vld1q_u8(d);
  65. q11u8 = vld1q_u8(d + 16);
  66. d += dst_stride;
  67. q0u8 = vrhaddq_u8(q0u8, q8u8);
  68. q1u8 = vrhaddq_u8(q1u8, q9u8);
  69. q2u8 = vrhaddq_u8(q2u8, q10u8);
  70. q3u8 = vrhaddq_u8(q3u8, q11u8);
  71. vst1q_u8(dst, q0u8);
  72. vst1q_u8(dst + 16, q1u8);
  73. dst += dst_stride;
  74. vst1q_u8(dst, q2u8);
  75. vst1q_u8(dst + 16, q3u8);
  76. dst += dst_stride;
  77. }
  78. } else if (w > 8) { // avg16
  79. for (; h > 0; h -= 2) {
  80. q0u8 = vld1q_u8(src);
  81. src += src_stride;
  82. q1u8 = vld1q_u8(src);
  83. src += src_stride;
  84. q2u8 = vld1q_u8(d);
  85. d += dst_stride;
  86. q3u8 = vld1q_u8(d);
  87. d += dst_stride;
  88. q0u8 = vrhaddq_u8(q0u8, q2u8);
  89. q1u8 = vrhaddq_u8(q1u8, q3u8);
  90. vst1q_u8(dst, q0u8);
  91. dst += dst_stride;
  92. vst1q_u8(dst, q1u8);
  93. dst += dst_stride;
  94. }
  95. } else if (w == 8) { // avg8
  96. for (; h > 0; h -= 2) {
  97. d0u8 = vld1_u8(src);
  98. src += src_stride;
  99. d1u8 = vld1_u8(src);
  100. src += src_stride;
  101. d2u8 = vld1_u8(d);
  102. d += dst_stride;
  103. d3u8 = vld1_u8(d);
  104. d += dst_stride;
  105. q0u8 = vcombine_u8(d0u8, d1u8);
  106. q1u8 = vcombine_u8(d2u8, d3u8);
  107. q0u8 = vrhaddq_u8(q0u8, q1u8);
  108. vst1_u8(dst, vget_low_u8(q0u8));
  109. dst += dst_stride;
  110. vst1_u8(dst, vget_high_u8(q0u8));
  111. dst += dst_stride;
  112. }
  113. } else { // avg4
  114. for (; h > 0; h -= 2) {
  115. d0u32 = vld1_lane_u32((const uint32_t *)src, d0u32, 0);
  116. src += src_stride;
  117. d0u32 = vld1_lane_u32((const uint32_t *)src, d0u32, 1);
  118. src += src_stride;
  119. d2u32 = vld1_lane_u32((const uint32_t *)d, d2u32, 0);
  120. d += dst_stride;
  121. d2u32 = vld1_lane_u32((const uint32_t *)d, d2u32, 1);
  122. d += dst_stride;
  123. d0u8 = vrhadd_u8(vreinterpret_u8_u32(d0u32),
  124. vreinterpret_u8_u32(d2u32));
  125. d0u32 = vreinterpret_u32_u8(d0u8);
  126. vst1_lane_u32((uint32_t *)dst, d0u32, 0);
  127. dst += dst_stride;
  128. vst1_lane_u32((uint32_t *)dst, d0u32, 1);
  129. dst += dst_stride;
  130. }
  131. }
  132. return;
  133. }