rotate_lsx.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright 2022 The LibYuv Project Authors. All rights reserved.
  3. *
  4. * Copyright (c) 2022 Loongson Technology Corporation Limited
  5. *
  6. * Use of this source code is governed by a BSD-style license
  7. * that can be found in the LICENSE file in the root of the source
  8. * tree. An additional intellectual property rights grant can be found
  9. * in the file PATENTS. All contributing project authors may
  10. * be found in the AUTHORS file in the root of the source tree.
  11. */
  12. #include "libyuv/rotate_row.h"
  13. #if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
  14. #include "libyuv/loongson_intrinsics.h"
  15. #ifdef __cplusplus
  16. namespace libyuv {
  17. extern "C" {
  18. #endif
  19. #define ILVLH_B(in0, in1, in2, in3, out0, out1, out2, out3) \
  20. { \
  21. DUP2_ARG2(__lsx_vilvl_b, in1, in0, in3, in2, out0, out2); \
  22. DUP2_ARG2(__lsx_vilvh_b, in1, in0, in3, in2, out1, out3); \
  23. }
  24. #define ILVLH_H(in0, in1, in2, in3, out0, out1, out2, out3) \
  25. { \
  26. DUP2_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, out0, out2); \
  27. DUP2_ARG2(__lsx_vilvh_h, in1, in0, in3, in2, out1, out3); \
  28. }
  29. #define ILVLH_W(in0, in1, in2, in3, out0, out1, out2, out3) \
  30. { \
  31. DUP2_ARG2(__lsx_vilvl_w, in1, in0, in3, in2, out0, out2); \
  32. DUP2_ARG2(__lsx_vilvh_w, in1, in0, in3, in2, out1, out3); \
  33. }
  34. #define ILVLH_D(in0, in1, in2, in3, out0, out1, out2, out3) \
  35. { \
  36. DUP2_ARG2(__lsx_vilvl_d, in1, in0, in3, in2, out0, out2); \
  37. DUP2_ARG2(__lsx_vilvh_d, in1, in0, in3, in2, out1, out3); \
  38. }
  39. #define LSX_ST_4(_dst0, _dst1, _dst2, _dst3, _dst, _stride, _stride2, \
  40. _stride3, _stride4) \
  41. { \
  42. __lsx_vst(_dst0, _dst, 0); \
  43. __lsx_vstx(_dst1, _dst, _stride); \
  44. __lsx_vstx(_dst2, _dst, _stride2); \
  45. __lsx_vstx(_dst3, _dst, _stride3); \
  46. _dst += _stride4; \
  47. }
  48. #define LSX_ST_2(_dst0, _dst1, _dst, _stride, _stride2) \
  49. { \
  50. __lsx_vst(_dst0, _dst, 0); \
  51. __lsx_vstx(_dst1, _dst, _stride); \
  52. _dst += _stride2; \
  53. }
  54. void TransposeUVWx16_C(const uint8_t* src,
  55. int src_stride,
  56. uint8_t* dst_a,
  57. int dst_stride_a,
  58. uint8_t* dst_b,
  59. int dst_stride_b,
  60. int width) {
  61. TransposeUVWx8_C(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b,
  62. width);
  63. TransposeUVWx8_C((src + 8 * src_stride), src_stride, (dst_a + 8),
  64. dst_stride_a, (dst_b + 8), dst_stride_b, width);
  65. }
  66. void TransposeWx16_LSX(const uint8_t* src,
  67. int src_stride,
  68. uint8_t* dst,
  69. int dst_stride,
  70. int width) {
  71. int x;
  72. int len = width / 16;
  73. uint8_t* s;
  74. int src_stride2 = src_stride << 1;
  75. int src_stride3 = src_stride + src_stride2;
  76. int src_stride4 = src_stride2 << 1;
  77. int dst_stride2 = dst_stride << 1;
  78. int dst_stride3 = dst_stride + dst_stride2;
  79. int dst_stride4 = dst_stride2 << 1;
  80. __m128i src0, src1, src2, src3, dst0, dst1, dst2, dst3;
  81. __m128i tmp0, tmp1, tmp2, tmp3;
  82. __m128i reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
  83. __m128i res0, res1, res2, res3, res4, res5, res6, res7, res8, res9;
  84. for (x = 0; x < len; x++) {
  85. s = (uint8_t*)src;
  86. src0 = __lsx_vld(s, 0);
  87. src1 = __lsx_vldx(s, src_stride);
  88. src2 = __lsx_vldx(s, src_stride2);
  89. src3 = __lsx_vldx(s, src_stride3);
  90. s += src_stride4;
  91. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  92. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg0, reg1, reg2, reg3);
  93. src0 = __lsx_vld(s, 0);
  94. src1 = __lsx_vldx(s, src_stride);
  95. src2 = __lsx_vldx(s, src_stride2);
  96. src3 = __lsx_vldx(s, src_stride3);
  97. s += src_stride4;
  98. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  99. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg4, reg5, reg6, reg7);
  100. ILVLH_W(reg0, reg4, reg1, reg5, res0, res1, res2, res3);
  101. ILVLH_W(reg2, reg6, reg3, reg7, res4, res5, res6, res7);
  102. src0 = __lsx_vld(s, 0);
  103. src1 = __lsx_vldx(s, src_stride);
  104. src2 = __lsx_vldx(s, src_stride2);
  105. src3 = __lsx_vldx(s, src_stride3);
  106. s += src_stride4;
  107. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  108. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg0, reg1, reg2, reg3);
  109. src0 = __lsx_vld(s, 0);
  110. src1 = __lsx_vldx(s, src_stride);
  111. src2 = __lsx_vldx(s, src_stride2);
  112. src3 = __lsx_vldx(s, src_stride3);
  113. s += src_stride4;
  114. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  115. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg4, reg5, reg6, reg7);
  116. res8 = __lsx_vilvl_w(reg4, reg0);
  117. res9 = __lsx_vilvh_w(reg4, reg0);
  118. ILVLH_D(res0, res8, res1, res9, dst0, dst1, dst2, dst3);
  119. LSX_ST_4(dst0, dst1, dst2, dst3, dst, dst_stride, dst_stride2, dst_stride3,
  120. dst_stride4);
  121. res8 = __lsx_vilvl_w(reg5, reg1);
  122. res9 = __lsx_vilvh_w(reg5, reg1);
  123. ILVLH_D(res2, res8, res3, res9, dst0, dst1, dst2, dst3);
  124. LSX_ST_4(dst0, dst1, dst2, dst3, dst, dst_stride, dst_stride2, dst_stride3,
  125. dst_stride4);
  126. res8 = __lsx_vilvl_w(reg6, reg2);
  127. res9 = __lsx_vilvh_w(reg6, reg2);
  128. ILVLH_D(res4, res8, res5, res9, dst0, dst1, dst2, dst3);
  129. LSX_ST_4(dst0, dst1, dst2, dst3, dst, dst_stride, dst_stride2, dst_stride3,
  130. dst_stride4);
  131. res8 = __lsx_vilvl_w(reg7, reg3);
  132. res9 = __lsx_vilvh_w(reg7, reg3);
  133. ILVLH_D(res6, res8, res7, res9, dst0, dst1, dst2, dst3);
  134. LSX_ST_4(dst0, dst1, dst2, dst3, dst, dst_stride, dst_stride2, dst_stride3,
  135. dst_stride4);
  136. src += 16;
  137. }
  138. }
  139. void TransposeUVWx16_LSX(const uint8_t* src,
  140. int src_stride,
  141. uint8_t* dst_a,
  142. int dst_stride_a,
  143. uint8_t* dst_b,
  144. int dst_stride_b,
  145. int width) {
  146. int x;
  147. int len = width / 8;
  148. uint8_t* s;
  149. int src_stride2 = src_stride << 1;
  150. int src_stride3 = src_stride + src_stride2;
  151. int src_stride4 = src_stride2 << 1;
  152. int dst_stride_a2 = dst_stride_a << 1;
  153. int dst_stride_b2 = dst_stride_b << 1;
  154. __m128i src0, src1, src2, src3, dst0, dst1, dst2, dst3;
  155. __m128i tmp0, tmp1, tmp2, tmp3;
  156. __m128i reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
  157. __m128i res0, res1, res2, res3, res4, res5, res6, res7, res8, res9;
  158. for (x = 0; x < len; x++) {
  159. s = (uint8_t*)src;
  160. src0 = __lsx_vld(s, 0);
  161. src1 = __lsx_vldx(s, src_stride);
  162. src2 = __lsx_vldx(s, src_stride2);
  163. src3 = __lsx_vldx(s, src_stride3);
  164. s += src_stride4;
  165. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  166. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg0, reg1, reg2, reg3);
  167. src0 = __lsx_vld(s, 0);
  168. src1 = __lsx_vldx(s, src_stride);
  169. src2 = __lsx_vldx(s, src_stride2);
  170. src3 = __lsx_vldx(s, src_stride3);
  171. s += src_stride4;
  172. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  173. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg4, reg5, reg6, reg7);
  174. ILVLH_W(reg0, reg4, reg1, reg5, res0, res1, res2, res3);
  175. ILVLH_W(reg2, reg6, reg3, reg7, res4, res5, res6, res7);
  176. src0 = __lsx_vld(s, 0);
  177. src1 = __lsx_vldx(s, src_stride);
  178. src2 = __lsx_vldx(s, src_stride2);
  179. src3 = __lsx_vldx(s, src_stride3);
  180. s += src_stride4;
  181. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  182. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg0, reg1, reg2, reg3);
  183. src0 = __lsx_vld(s, 0);
  184. src1 = __lsx_vldx(s, src_stride);
  185. src2 = __lsx_vldx(s, src_stride2);
  186. src3 = __lsx_vldx(s, src_stride3);
  187. s += src_stride4;
  188. ILVLH_B(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3);
  189. ILVLH_H(tmp0, tmp2, tmp1, tmp3, reg4, reg5, reg6, reg7);
  190. res8 = __lsx_vilvl_w(reg4, reg0);
  191. res9 = __lsx_vilvh_w(reg4, reg0);
  192. ILVLH_D(res0, res8, res1, res9, dst0, dst1, dst2, dst3);
  193. LSX_ST_2(dst0, dst2, dst_a, dst_stride_a, dst_stride_a2);
  194. LSX_ST_2(dst1, dst3, dst_b, dst_stride_b, dst_stride_b2);
  195. res8 = __lsx_vilvl_w(reg5, reg1);
  196. res9 = __lsx_vilvh_w(reg5, reg1);
  197. ILVLH_D(res2, res8, res3, res9, dst0, dst1, dst2, dst3);
  198. LSX_ST_2(dst0, dst2, dst_a, dst_stride_a, dst_stride_a2);
  199. LSX_ST_2(dst1, dst3, dst_b, dst_stride_b, dst_stride_b2);
  200. res8 = __lsx_vilvl_w(reg6, reg2);
  201. res9 = __lsx_vilvh_w(reg6, reg2);
  202. ILVLH_D(res4, res8, res5, res9, dst0, dst1, dst2, dst3);
  203. LSX_ST_2(dst0, dst2, dst_a, dst_stride_a, dst_stride_a2);
  204. LSX_ST_2(dst1, dst3, dst_b, dst_stride_b, dst_stride_b2);
  205. res8 = __lsx_vilvl_w(reg7, reg3);
  206. res9 = __lsx_vilvh_w(reg7, reg3);
  207. ILVLH_D(res6, res8, res7, res9, dst0, dst1, dst2, dst3);
  208. LSX_ST_2(dst0, dst2, dst_a, dst_stride_a, dst_stride_a2);
  209. LSX_ST_2(dst1, dst3, dst_b, dst_stride_b, dst_stride_b2);
  210. src += 16;
  211. }
  212. }
  213. #ifdef __cplusplus
  214. } // extern "C"
  215. } // namespace libyuv
  216. #endif
  217. #endif // !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)