dec_sse2.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. // Copyright 2011 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. //
  10. // SSE2 version of some decoding functions (idct, loop filtering).
  11. //
  12. // Author: somnath@google.com (Somnath Banerjee)
  13. // cduvivier@google.com (Christian Duvivier)
  14. #include "./dsp.h"
  15. #if defined(WEBP_USE_SSE2)
  16. // The 3-coeff sparse transform in SSE2 is not really faster than the plain-C
  17. // one it seems => disable it by default. Uncomment the following to enable:
  18. #if !defined(USE_TRANSFORM_AC3)
  19. #define USE_TRANSFORM_AC3 0 // ALTERNATE_CODE
  20. #endif
  21. #include <emmintrin.h>
  22. #include "./common_sse2.h"
  23. #include "../dec/vp8i_dec.h"
  24. #include "../utils/utils.h"
  25. //------------------------------------------------------------------------------
  26. // Transforms (Paragraph 14.4)
  27. static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) {
  28. // This implementation makes use of 16-bit fixed point versions of two
  29. // multiply constants:
  30. // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
  31. // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
  32. //
  33. // To be able to use signed 16-bit integers, we use the following trick to
  34. // have constants within range:
  35. // - Associated constants are obtained by subtracting the 16-bit fixed point
  36. // version of one:
  37. // k = K - (1 << 16) => K = k + (1 << 16)
  38. // K1 = 85267 => k1 = 20091
  39. // K2 = 35468 => k2 = -30068
  40. // - The multiplication of a variable by a constant become the sum of the
  41. // variable and the multiplication of that variable by the associated
  42. // constant:
  43. // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
  44. const __m128i k1 = _mm_set1_epi16(20091);
  45. const __m128i k2 = _mm_set1_epi16(-30068);
  46. __m128i T0, T1, T2, T3;
  47. // Load and concatenate the transform coefficients (we'll do two transforms
  48. // in parallel). In the case of only one transform, the second half of the
  49. // vectors will just contain random value we'll never use nor store.
  50. __m128i in0, in1, in2, in3;
  51. {
  52. in0 = _mm_loadl_epi64((const __m128i*)&in[0]);
  53. in1 = _mm_loadl_epi64((const __m128i*)&in[4]);
  54. in2 = _mm_loadl_epi64((const __m128i*)&in[8]);
  55. in3 = _mm_loadl_epi64((const __m128i*)&in[12]);
  56. // a00 a10 a20 a30 x x x x
  57. // a01 a11 a21 a31 x x x x
  58. // a02 a12 a22 a32 x x x x
  59. // a03 a13 a23 a33 x x x x
  60. if (do_two) {
  61. const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]);
  62. const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]);
  63. const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]);
  64. const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]);
  65. in0 = _mm_unpacklo_epi64(in0, inB0);
  66. in1 = _mm_unpacklo_epi64(in1, inB1);
  67. in2 = _mm_unpacklo_epi64(in2, inB2);
  68. in3 = _mm_unpacklo_epi64(in3, inB3);
  69. // a00 a10 a20 a30 b00 b10 b20 b30
  70. // a01 a11 a21 a31 b01 b11 b21 b31
  71. // a02 a12 a22 a32 b02 b12 b22 b32
  72. // a03 a13 a23 a33 b03 b13 b23 b33
  73. }
  74. }
  75. // Vertical pass and subsequent transpose.
  76. {
  77. // First pass, c and d calculations are longer because of the "trick"
  78. // multiplications.
  79. const __m128i a = _mm_add_epi16(in0, in2);
  80. const __m128i b = _mm_sub_epi16(in0, in2);
  81. // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
  82. const __m128i c1 = _mm_mulhi_epi16(in1, k2);
  83. const __m128i c2 = _mm_mulhi_epi16(in3, k1);
  84. const __m128i c3 = _mm_sub_epi16(in1, in3);
  85. const __m128i c4 = _mm_sub_epi16(c1, c2);
  86. const __m128i c = _mm_add_epi16(c3, c4);
  87. // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
  88. const __m128i d1 = _mm_mulhi_epi16(in1, k1);
  89. const __m128i d2 = _mm_mulhi_epi16(in3, k2);
  90. const __m128i d3 = _mm_add_epi16(in1, in3);
  91. const __m128i d4 = _mm_add_epi16(d1, d2);
  92. const __m128i d = _mm_add_epi16(d3, d4);
  93. // Second pass.
  94. const __m128i tmp0 = _mm_add_epi16(a, d);
  95. const __m128i tmp1 = _mm_add_epi16(b, c);
  96. const __m128i tmp2 = _mm_sub_epi16(b, c);
  97. const __m128i tmp3 = _mm_sub_epi16(a, d);
  98. // Transpose the two 4x4.
  99. VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3);
  100. }
  101. // Horizontal pass and subsequent transpose.
  102. {
  103. // First pass, c and d calculations are longer because of the "trick"
  104. // multiplications.
  105. const __m128i four = _mm_set1_epi16(4);
  106. const __m128i dc = _mm_add_epi16(T0, four);
  107. const __m128i a = _mm_add_epi16(dc, T2);
  108. const __m128i b = _mm_sub_epi16(dc, T2);
  109. // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
  110. const __m128i c1 = _mm_mulhi_epi16(T1, k2);
  111. const __m128i c2 = _mm_mulhi_epi16(T3, k1);
  112. const __m128i c3 = _mm_sub_epi16(T1, T3);
  113. const __m128i c4 = _mm_sub_epi16(c1, c2);
  114. const __m128i c = _mm_add_epi16(c3, c4);
  115. // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
  116. const __m128i d1 = _mm_mulhi_epi16(T1, k1);
  117. const __m128i d2 = _mm_mulhi_epi16(T3, k2);
  118. const __m128i d3 = _mm_add_epi16(T1, T3);
  119. const __m128i d4 = _mm_add_epi16(d1, d2);
  120. const __m128i d = _mm_add_epi16(d3, d4);
  121. // Second pass.
  122. const __m128i tmp0 = _mm_add_epi16(a, d);
  123. const __m128i tmp1 = _mm_add_epi16(b, c);
  124. const __m128i tmp2 = _mm_sub_epi16(b, c);
  125. const __m128i tmp3 = _mm_sub_epi16(a, d);
  126. const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
  127. const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
  128. const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
  129. const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
  130. // Transpose the two 4x4.
  131. VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1,
  132. &T2, &T3);
  133. }
  134. // Add inverse transform to 'dst' and store.
  135. {
  136. const __m128i zero = _mm_setzero_si128();
  137. // Load the reference(s).
  138. __m128i dst0, dst1, dst2, dst3;
  139. if (do_two) {
  140. // Load eight bytes/pixels per line.
  141. dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS));
  142. dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS));
  143. dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS));
  144. dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS));
  145. } else {
  146. // Load four bytes/pixels per line.
  147. dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS));
  148. dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS));
  149. dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS));
  150. dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS));
  151. }
  152. // Convert to 16b.
  153. dst0 = _mm_unpacklo_epi8(dst0, zero);
  154. dst1 = _mm_unpacklo_epi8(dst1, zero);
  155. dst2 = _mm_unpacklo_epi8(dst2, zero);
  156. dst3 = _mm_unpacklo_epi8(dst3, zero);
  157. // Add the inverse transform(s).
  158. dst0 = _mm_add_epi16(dst0, T0);
  159. dst1 = _mm_add_epi16(dst1, T1);
  160. dst2 = _mm_add_epi16(dst2, T2);
  161. dst3 = _mm_add_epi16(dst3, T3);
  162. // Unsigned saturate to 8b.
  163. dst0 = _mm_packus_epi16(dst0, dst0);
  164. dst1 = _mm_packus_epi16(dst1, dst1);
  165. dst2 = _mm_packus_epi16(dst2, dst2);
  166. dst3 = _mm_packus_epi16(dst3, dst3);
  167. // Store the results.
  168. if (do_two) {
  169. // Store eight bytes/pixels per line.
  170. _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0);
  171. _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1);
  172. _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2);
  173. _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3);
  174. } else {
  175. // Store four bytes/pixels per line.
  176. WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0));
  177. WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1));
  178. WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2));
  179. WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3));
  180. }
  181. }
  182. }
  183. #if (USE_TRANSFORM_AC3 == 1)
  184. #define MUL(a, b) (((a) * (b)) >> 16)
  185. static void TransformAC3(const int16_t* in, uint8_t* dst) {
  186. static const int kC1 = 20091 + (1 << 16);
  187. static const int kC2 = 35468;
  188. const __m128i A = _mm_set1_epi16(in[0] + 4);
  189. const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2));
  190. const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1));
  191. const int c1 = MUL(in[1], kC2);
  192. const int d1 = MUL(in[1], kC1);
  193. const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1);
  194. const __m128i B = _mm_adds_epi16(A, CD);
  195. const __m128i m0 = _mm_adds_epi16(B, d4);
  196. const __m128i m1 = _mm_adds_epi16(B, c4);
  197. const __m128i m2 = _mm_subs_epi16(B, c4);
  198. const __m128i m3 = _mm_subs_epi16(B, d4);
  199. const __m128i zero = _mm_setzero_si128();
  200. // Load the source pixels.
  201. __m128i dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS));
  202. __m128i dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS));
  203. __m128i dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS));
  204. __m128i dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS));
  205. // Convert to 16b.
  206. dst0 = _mm_unpacklo_epi8(dst0, zero);
  207. dst1 = _mm_unpacklo_epi8(dst1, zero);
  208. dst2 = _mm_unpacklo_epi8(dst2, zero);
  209. dst3 = _mm_unpacklo_epi8(dst3, zero);
  210. // Add the inverse transform.
  211. dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3));
  212. dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3));
  213. dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3));
  214. dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3));
  215. // Unsigned saturate to 8b.
  216. dst0 = _mm_packus_epi16(dst0, dst0);
  217. dst1 = _mm_packus_epi16(dst1, dst1);
  218. dst2 = _mm_packus_epi16(dst2, dst2);
  219. dst3 = _mm_packus_epi16(dst3, dst3);
  220. // Store the results.
  221. WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0));
  222. WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1));
  223. WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2));
  224. WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3));
  225. }
  226. #undef MUL
  227. #endif // USE_TRANSFORM_AC3
  228. //------------------------------------------------------------------------------
  229. // Loop Filter (Paragraph 15)
  230. // Compute abs(p - q) = subs(p - q) OR subs(q - p)
  231. #define MM_ABS(p, q) _mm_or_si128( \
  232. _mm_subs_epu8((q), (p)), \
  233. _mm_subs_epu8((p), (q)))
  234. // Shift each byte of "x" by 3 bits while preserving by the sign bit.
  235. static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) {
  236. const __m128i zero = _mm_setzero_si128();
  237. const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x);
  238. const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x);
  239. const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8);
  240. const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8);
  241. *x = _mm_packs_epi16(lo_1, hi_1);
  242. }
  243. #define FLIP_SIGN_BIT2(a, b) { \
  244. (a) = _mm_xor_si128(a, sign_bit); \
  245. (b) = _mm_xor_si128(b, sign_bit); \
  246. }
  247. #define FLIP_SIGN_BIT4(a, b, c, d) { \
  248. FLIP_SIGN_BIT2(a, b); \
  249. FLIP_SIGN_BIT2(c, d); \
  250. }
  251. // input/output is uint8_t
  252. static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1,
  253. const __m128i* const p0,
  254. const __m128i* const q0,
  255. const __m128i* const q1,
  256. int hev_thresh, __m128i* const not_hev) {
  257. const __m128i zero = _mm_setzero_si128();
  258. const __m128i t_1 = MM_ABS(*p1, *p0);
  259. const __m128i t_2 = MM_ABS(*q1, *q0);
  260. const __m128i h = _mm_set1_epi8(hev_thresh);
  261. const __m128i t_max = _mm_max_epu8(t_1, t_2);
  262. const __m128i t_max_h = _mm_subs_epu8(t_max, h);
  263. *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2
  264. }
  265. // input pixels are int8_t
  266. static WEBP_INLINE void GetBaseDelta_SSE2(const __m128i* const p1,
  267. const __m128i* const p0,
  268. const __m128i* const q0,
  269. const __m128i* const q1,
  270. __m128i* const delta) {
  271. // beware of addition order, for saturation!
  272. const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
  273. const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0
  274. const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0)
  275. const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0)
  276. const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0)
  277. *delta = s3;
  278. }
  279. // input and output are int8_t
  280. static WEBP_INLINE void DoSimpleFilter_SSE2(__m128i* const p0,
  281. __m128i* const q0,
  282. const __m128i* const fl) {
  283. const __m128i k3 = _mm_set1_epi8(3);
  284. const __m128i k4 = _mm_set1_epi8(4);
  285. __m128i v3 = _mm_adds_epi8(*fl, k3);
  286. __m128i v4 = _mm_adds_epi8(*fl, k4);
  287. SignedShift8b_SSE2(&v4); // v4 >> 3
  288. SignedShift8b_SSE2(&v3); // v3 >> 3
  289. *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4
  290. *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3
  291. }
  292. // Updates values of 2 pixels at MB edge during complex filtering.
  293. // Update operations:
  294. // q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)]
  295. // Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip).
  296. static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi,
  297. const __m128i* const a0_lo,
  298. const __m128i* const a0_hi) {
  299. const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7);
  300. const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7);
  301. const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi);
  302. const __m128i sign_bit = _mm_set1_epi8((char)0x80);
  303. *pi = _mm_adds_epi8(*pi, delta);
  304. *qi = _mm_subs_epi8(*qi, delta);
  305. FLIP_SIGN_BIT2(*pi, *qi);
  306. }
  307. // input pixels are uint8_t
  308. static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1,
  309. const __m128i* const p0,
  310. const __m128i* const q0,
  311. const __m128i* const q1,
  312. int thresh, __m128i* const mask) {
  313. const __m128i m_thresh = _mm_set1_epi8((char)thresh);
  314. const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
  315. const __m128i kFE = _mm_set1_epi8((char)0xFE);
  316. const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero
  317. const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2
  318. const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0)
  319. const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2
  320. const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2
  321. const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh
  322. *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128());
  323. }
  324. //------------------------------------------------------------------------------
  325. // Edge filtering functions
  326. // Applies filter on 2 pixels (p0 and q0)
  327. static WEBP_INLINE void DoFilter2_SSE2(__m128i* const p1, __m128i* const p0,
  328. __m128i* const q0, __m128i* const q1,
  329. int thresh) {
  330. __m128i a, mask;
  331. const __m128i sign_bit = _mm_set1_epi8((char)0x80);
  332. // convert p1/q1 to int8_t (for GetBaseDelta_SSE2)
  333. const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
  334. const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
  335. NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &mask);
  336. FLIP_SIGN_BIT2(*p0, *q0);
  337. GetBaseDelta_SSE2(&p1s, p0, q0, &q1s, &a);
  338. a = _mm_and_si128(a, mask); // mask filter values we don't care about
  339. DoSimpleFilter_SSE2(p0, q0, &a);
  340. FLIP_SIGN_BIT2(*p0, *q0);
  341. }
  342. // Applies filter on 4 pixels (p1, p0, q0 and q1)
  343. static WEBP_INLINE void DoFilter4_SSE2(__m128i* const p1, __m128i* const p0,
  344. __m128i* const q0, __m128i* const q1,
  345. const __m128i* const mask,
  346. int hev_thresh) {
  347. const __m128i zero = _mm_setzero_si128();
  348. const __m128i sign_bit = _mm_set1_epi8((char)0x80);
  349. const __m128i k64 = _mm_set1_epi8(64);
  350. const __m128i k3 = _mm_set1_epi8(3);
  351. const __m128i k4 = _mm_set1_epi8(4);
  352. __m128i not_hev;
  353. __m128i t1, t2, t3;
  354. // compute hev mask
  355. GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, &not_hev);
  356. // convert to signed values
  357. FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
  358. t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
  359. t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1)
  360. t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0
  361. t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0)
  362. t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0)
  363. t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0)
  364. t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about
  365. t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3
  366. t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4
  367. SignedShift8b_SSE2(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3
  368. SignedShift8b_SSE2(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3
  369. *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2
  370. *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3
  371. FLIP_SIGN_BIT2(*p0, *q0);
  372. // this is equivalent to signed (a + 1) >> 1 calculation
  373. t2 = _mm_add_epi8(t3, sign_bit);
  374. t3 = _mm_avg_epu8(t2, zero);
  375. t3 = _mm_sub_epi8(t3, k64);
  376. t3 = _mm_and_si128(not_hev, t3); // if !hev
  377. *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3
  378. *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3
  379. FLIP_SIGN_BIT2(*p1, *q1);
  380. }
  381. // Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2)
  382. static WEBP_INLINE void DoFilter6_SSE2(__m128i* const p2, __m128i* const p1,
  383. __m128i* const p0, __m128i* const q0,
  384. __m128i* const q1, __m128i* const q2,
  385. const __m128i* const mask,
  386. int hev_thresh) {
  387. const __m128i zero = _mm_setzero_si128();
  388. const __m128i sign_bit = _mm_set1_epi8((char)0x80);
  389. __m128i a, not_hev;
  390. // compute hev mask
  391. GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, &not_hev);
  392. FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
  393. FLIP_SIGN_BIT2(*p2, *q2);
  394. GetBaseDelta_SSE2(p1, p0, q0, q1, &a);
  395. { // do simple filter on pixels with hev
  396. const __m128i m = _mm_andnot_si128(not_hev, *mask);
  397. const __m128i f = _mm_and_si128(a, m);
  398. DoSimpleFilter_SSE2(p0, q0, &f);
  399. }
  400. { // do strong filter on pixels with not hev
  401. const __m128i k9 = _mm_set1_epi16(0x0900);
  402. const __m128i k63 = _mm_set1_epi16(63);
  403. const __m128i m = _mm_and_si128(not_hev, *mask);
  404. const __m128i f = _mm_and_si128(a, m);
  405. const __m128i f_lo = _mm_unpacklo_epi8(zero, f);
  406. const __m128i f_hi = _mm_unpackhi_epi8(zero, f);
  407. const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9
  408. const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9
  409. const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63
  410. const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63
  411. const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63
  412. const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63
  413. const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63
  414. const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63
  415. Update2Pixels_SSE2(p2, q2, &a2_lo, &a2_hi);
  416. Update2Pixels_SSE2(p1, q1, &a1_lo, &a1_hi);
  417. Update2Pixels_SSE2(p0, q0, &a0_lo, &a0_hi);
  418. }
  419. }
  420. // reads 8 rows across a vertical edge.
  421. static WEBP_INLINE void Load8x4_SSE2(const uint8_t* const b, int stride,
  422. __m128i* const p, __m128i* const q) {
  423. // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00
  424. // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10
  425. const __m128i A0 = _mm_set_epi32(
  426. WebPMemToUint32(&b[6 * stride]), WebPMemToUint32(&b[2 * stride]),
  427. WebPMemToUint32(&b[4 * stride]), WebPMemToUint32(&b[0 * stride]));
  428. const __m128i A1 = _mm_set_epi32(
  429. WebPMemToUint32(&b[7 * stride]), WebPMemToUint32(&b[3 * stride]),
  430. WebPMemToUint32(&b[5 * stride]), WebPMemToUint32(&b[1 * stride]));
  431. // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
  432. // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
  433. const __m128i B0 = _mm_unpacklo_epi8(A0, A1);
  434. const __m128i B1 = _mm_unpackhi_epi8(A0, A1);
  435. // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
  436. // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
  437. const __m128i C0 = _mm_unpacklo_epi16(B0, B1);
  438. const __m128i C1 = _mm_unpackhi_epi16(B0, B1);
  439. // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
  440. // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
  441. *p = _mm_unpacklo_epi32(C0, C1);
  442. *q = _mm_unpackhi_epi32(C0, C1);
  443. }
  444. static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0,
  445. const uint8_t* const r8,
  446. int stride,
  447. __m128i* const p1, __m128i* const p0,
  448. __m128i* const q0, __m128i* const q1) {
  449. // Assume the pixels around the edge (|) are numbered as follows
  450. // 00 01 | 02 03
  451. // 10 11 | 12 13
  452. // ... | ...
  453. // e0 e1 | e2 e3
  454. // f0 f1 | f2 f3
  455. //
  456. // r0 is pointing to the 0th row (00)
  457. // r8 is pointing to the 8th row (80)
  458. // Load
  459. // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
  460. // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
  461. // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
  462. // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
  463. Load8x4_SSE2(r0, stride, p1, q0);
  464. Load8x4_SSE2(r8, stride, p0, q1);
  465. {
  466. // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
  467. // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
  468. // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
  469. // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
  470. const __m128i t1 = *p1;
  471. const __m128i t2 = *q0;
  472. *p1 = _mm_unpacklo_epi64(t1, *p0);
  473. *p0 = _mm_unpackhi_epi64(t1, *p0);
  474. *q0 = _mm_unpacklo_epi64(t2, *q1);
  475. *q1 = _mm_unpackhi_epi64(t2, *q1);
  476. }
  477. }
  478. static WEBP_INLINE void Store4x4_SSE2(__m128i* const x,
  479. uint8_t* dst, int stride) {
  480. int i;
  481. for (i = 0; i < 4; ++i, dst += stride) {
  482. WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x));
  483. *x = _mm_srli_si128(*x, 4);
  484. }
  485. }
  486. // Transpose back and store
  487. static WEBP_INLINE void Store16x4_SSE2(const __m128i* const p1,
  488. const __m128i* const p0,
  489. const __m128i* const q0,
  490. const __m128i* const q1,
  491. uint8_t* r0, uint8_t* r8,
  492. int stride) {
  493. __m128i t1, p1_s, p0_s, q0_s, q1_s;
  494. // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
  495. // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
  496. t1 = *p0;
  497. p0_s = _mm_unpacklo_epi8(*p1, t1);
  498. p1_s = _mm_unpackhi_epi8(*p1, t1);
  499. // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
  500. // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
  501. t1 = *q0;
  502. q0_s = _mm_unpacklo_epi8(t1, *q1);
  503. q1_s = _mm_unpackhi_epi8(t1, *q1);
  504. // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
  505. // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
  506. t1 = p0_s;
  507. p0_s = _mm_unpacklo_epi16(t1, q0_s);
  508. q0_s = _mm_unpackhi_epi16(t1, q0_s);
  509. // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
  510. // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
  511. t1 = p1_s;
  512. p1_s = _mm_unpacklo_epi16(t1, q1_s);
  513. q1_s = _mm_unpackhi_epi16(t1, q1_s);
  514. Store4x4_SSE2(&p0_s, r0, stride);
  515. r0 += 4 * stride;
  516. Store4x4_SSE2(&q0_s, r0, stride);
  517. Store4x4_SSE2(&p1_s, r8, stride);
  518. r8 += 4 * stride;
  519. Store4x4_SSE2(&q1_s, r8, stride);
  520. }
  521. //------------------------------------------------------------------------------
  522. // Simple In-loop filtering (Paragraph 15.2)
  523. static void SimpleVFilter16_SSE2(uint8_t* p, int stride, int thresh) {
  524. // Load
  525. __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]);
  526. __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]);
  527. __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]);
  528. __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]);
  529. DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh);
  530. // Store
  531. _mm_storeu_si128((__m128i*)&p[-stride], p0);
  532. _mm_storeu_si128((__m128i*)&p[0], q0);
  533. }
  534. static void SimpleHFilter16_SSE2(uint8_t* p, int stride, int thresh) {
  535. __m128i p1, p0, q0, q1;
  536. p -= 2; // beginning of p1
  537. Load16x4_SSE2(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
  538. DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh);
  539. Store16x4_SSE2(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride);
  540. }
  541. static void SimpleVFilter16i_SSE2(uint8_t* p, int stride, int thresh) {
  542. int k;
  543. for (k = 3; k > 0; --k) {
  544. p += 4 * stride;
  545. SimpleVFilter16_SSE2(p, stride, thresh);
  546. }
  547. }
  548. static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) {
  549. int k;
  550. for (k = 3; k > 0; --k) {
  551. p += 4;
  552. SimpleHFilter16_SSE2(p, stride, thresh);
  553. }
  554. }
  555. //------------------------------------------------------------------------------
  556. // Complex In-loop filtering (Paragraph 15.3)
  557. #define MAX_DIFF1(p3, p2, p1, p0, m) do { \
  558. (m) = MM_ABS(p1, p0); \
  559. (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \
  560. (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \
  561. } while (0)
  562. #define MAX_DIFF2(p3, p2, p1, p0, m) do { \
  563. (m) = _mm_max_epu8(m, MM_ABS(p1, p0)); \
  564. (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \
  565. (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \
  566. } while (0)
  567. #define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \
  568. (e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \
  569. (e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \
  570. (e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \
  571. (e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \
  572. }
  573. #define LOADUV_H_EDGE(p, u, v, stride) do { \
  574. const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
  575. const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \
  576. (p) = _mm_unpacklo_epi64(U, V); \
  577. } while (0)
  578. #define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \
  579. LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \
  580. LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \
  581. LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \
  582. LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \
  583. }
  584. #define STOREUV(p, u, v, stride) { \
  585. _mm_storel_epi64((__m128i*)&(u)[(stride)], p); \
  586. (p) = _mm_srli_si128(p, 8); \
  587. _mm_storel_epi64((__m128i*)&(v)[(stride)], p); \
  588. }
  589. static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1,
  590. const __m128i* const p0,
  591. const __m128i* const q0,
  592. const __m128i* const q1,
  593. int thresh, int ithresh,
  594. __m128i* const mask) {
  595. const __m128i it = _mm_set1_epi8(ithresh);
  596. const __m128i diff = _mm_subs_epu8(*mask, it);
  597. const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128());
  598. __m128i filter_mask;
  599. NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &filter_mask);
  600. *mask = _mm_and_si128(thresh_mask, filter_mask);
  601. }
  602. // on macroblock edges
  603. static void VFilter16_SSE2(uint8_t* p, int stride,
  604. int thresh, int ithresh, int hev_thresh) {
  605. __m128i t1;
  606. __m128i mask;
  607. __m128i p2, p1, p0, q0, q1, q2;
  608. // Load p3, p2, p1, p0
  609. LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0);
  610. MAX_DIFF1(t1, p2, p1, p0, mask);
  611. // Load q0, q1, q2, q3
  612. LOAD_H_EDGES4(p, stride, q0, q1, q2, t1);
  613. MAX_DIFF2(t1, q2, q1, q0, mask);
  614. ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
  615. DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
  616. // Store
  617. _mm_storeu_si128((__m128i*)&p[-3 * stride], p2);
  618. _mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
  619. _mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
  620. _mm_storeu_si128((__m128i*)&p[+0 * stride], q0);
  621. _mm_storeu_si128((__m128i*)&p[+1 * stride], q1);
  622. _mm_storeu_si128((__m128i*)&p[+2 * stride], q2);
  623. }
  624. static void HFilter16_SSE2(uint8_t* p, int stride,
  625. int thresh, int ithresh, int hev_thresh) {
  626. __m128i mask;
  627. __m128i p3, p2, p1, p0, q0, q1, q2, q3;
  628. uint8_t* const b = p - 4;
  629. Load16x4_SSE2(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0);
  630. MAX_DIFF1(p3, p2, p1, p0, mask);
  631. Load16x4_SSE2(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3);
  632. MAX_DIFF2(q3, q2, q1, q0, mask);
  633. ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
  634. DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
  635. Store16x4_SSE2(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride);
  636. Store16x4_SSE2(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride);
  637. }
  638. // on three inner edges
  639. static void VFilter16i_SSE2(uint8_t* p, int stride,
  640. int thresh, int ithresh, int hev_thresh) {
  641. int k;
  642. __m128i p3, p2, p1, p0; // loop invariants
  643. LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue
  644. for (k = 3; k > 0; --k) {
  645. __m128i mask, tmp1, tmp2;
  646. uint8_t* const b = p + 2 * stride; // beginning of p1
  647. p += 4 * stride;
  648. MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
  649. LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2);
  650. MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
  651. // p3 and p2 are not just temporary variables here: they will be
  652. // re-used for next span. And q2/q3 will become p1/p0 accordingly.
  653. ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
  654. DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh);
  655. // Store
  656. _mm_storeu_si128((__m128i*)&b[0 * stride], p1);
  657. _mm_storeu_si128((__m128i*)&b[1 * stride], p0);
  658. _mm_storeu_si128((__m128i*)&b[2 * stride], p3);
  659. _mm_storeu_si128((__m128i*)&b[3 * stride], p2);
  660. // rotate samples
  661. p1 = tmp1;
  662. p0 = tmp2;
  663. }
  664. }
  665. static void HFilter16i_SSE2(uint8_t* p, int stride,
  666. int thresh, int ithresh, int hev_thresh) {
  667. int k;
  668. __m128i p3, p2, p1, p0; // loop invariants
  669. Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue
  670. for (k = 3; k > 0; --k) {
  671. __m128i mask, tmp1, tmp2;
  672. uint8_t* const b = p + 2; // beginning of p1
  673. p += 4; // beginning of q0 (and next span)
  674. MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
  675. Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2);
  676. MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
  677. ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
  678. DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh);
  679. Store16x4_SSE2(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride);
  680. // rotate samples
  681. p1 = tmp1;
  682. p0 = tmp2;
  683. }
  684. }
  685. // 8-pixels wide variant, for chroma filtering
  686. static void VFilter8_SSE2(uint8_t* u, uint8_t* v, int stride,
  687. int thresh, int ithresh, int hev_thresh) {
  688. __m128i mask;
  689. __m128i t1, p2, p1, p0, q0, q1, q2;
  690. // Load p3, p2, p1, p0
  691. LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0);
  692. MAX_DIFF1(t1, p2, p1, p0, mask);
  693. // Load q0, q1, q2, q3
  694. LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1);
  695. MAX_DIFF2(t1, q2, q1, q0, mask);
  696. ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
  697. DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
  698. // Store
  699. STOREUV(p2, u, v, -3 * stride);
  700. STOREUV(p1, u, v, -2 * stride);
  701. STOREUV(p0, u, v, -1 * stride);
  702. STOREUV(q0, u, v, 0 * stride);
  703. STOREUV(q1, u, v, 1 * stride);
  704. STOREUV(q2, u, v, 2 * stride);
  705. }
  706. static void HFilter8_SSE2(uint8_t* u, uint8_t* v, int stride,
  707. int thresh, int ithresh, int hev_thresh) {
  708. __m128i mask;
  709. __m128i p3, p2, p1, p0, q0, q1, q2, q3;
  710. uint8_t* const tu = u - 4;
  711. uint8_t* const tv = v - 4;
  712. Load16x4_SSE2(tu, tv, stride, &p3, &p2, &p1, &p0);
  713. MAX_DIFF1(p3, p2, p1, p0, mask);
  714. Load16x4_SSE2(u, v, stride, &q0, &q1, &q2, &q3);
  715. MAX_DIFF2(q3, q2, q1, q0, mask);
  716. ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
  717. DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
  718. Store16x4_SSE2(&p3, &p2, &p1, &p0, tu, tv, stride);
  719. Store16x4_SSE2(&q0, &q1, &q2, &q3, u, v, stride);
  720. }
  721. static void VFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride,
  722. int thresh, int ithresh, int hev_thresh) {
  723. __m128i mask;
  724. __m128i t1, t2, p1, p0, q0, q1;
  725. // Load p3, p2, p1, p0
  726. LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0);
  727. MAX_DIFF1(t2, t1, p1, p0, mask);
  728. u += 4 * stride;
  729. v += 4 * stride;
  730. // Load q0, q1, q2, q3
  731. LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2);
  732. MAX_DIFF2(t2, t1, q1, q0, mask);
  733. ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
  734. DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh);
  735. // Store
  736. STOREUV(p1, u, v, -2 * stride);
  737. STOREUV(p0, u, v, -1 * stride);
  738. STOREUV(q0, u, v, 0 * stride);
  739. STOREUV(q1, u, v, 1 * stride);
  740. }
  741. static void HFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride,
  742. int thresh, int ithresh, int hev_thresh) {
  743. __m128i mask;
  744. __m128i t1, t2, p1, p0, q0, q1;
  745. Load16x4_SSE2(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
  746. MAX_DIFF1(t2, t1, p1, p0, mask);
  747. u += 4; // beginning of q0
  748. v += 4;
  749. Load16x4_SSE2(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
  750. MAX_DIFF2(t2, t1, q1, q0, mask);
  751. ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
  752. DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh);
  753. u -= 2; // beginning of p1
  754. v -= 2;
  755. Store16x4_SSE2(&p1, &p0, &q0, &q1, u, v, stride);
  756. }
  757. //------------------------------------------------------------------------------
  758. // 4x4 predictions
  759. #define DST(x, y) dst[(x) + (y) * BPS]
  760. #define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
  761. // We use the following 8b-arithmetic tricks:
  762. // (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1
  763. // where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1]
  764. // and:
  765. // (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb
  766. // where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1
  767. // and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1
  768. static void VE4_SSE2(uint8_t* dst) { // vertical
  769. const __m128i one = _mm_set1_epi8(1);
  770. const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
  771. const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
  772. const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
  773. const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00);
  774. const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
  775. const __m128i b = _mm_subs_epu8(a, lsb);
  776. const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
  777. const uint32_t vals = _mm_cvtsi128_si32(avg);
  778. int i;
  779. for (i = 0; i < 4; ++i) {
  780. WebPUint32ToMem(dst + i * BPS, vals);
  781. }
  782. }
  783. static void LD4_SSE2(uint8_t* dst) { // Down-Left
  784. const __m128i one = _mm_set1_epi8(1);
  785. const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS));
  786. const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
  787. const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
  788. const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3);
  789. const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0);
  790. const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
  791. const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
  792. const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
  793. WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
  794. WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
  795. WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
  796. WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
  797. }
  798. static void VR4_SSE2(uint8_t* dst) { // Vertical-Right
  799. const __m128i one = _mm_set1_epi8(1);
  800. const int I = dst[-1 + 0 * BPS];
  801. const int J = dst[-1 + 1 * BPS];
  802. const int K = dst[-1 + 2 * BPS];
  803. const int X = dst[-1 - BPS];
  804. const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
  805. const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
  806. const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
  807. const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
  808. const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0);
  809. const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
  810. const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
  811. const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
  812. const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
  813. WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
  814. WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
  815. WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
  816. WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
  817. // these two are hard to implement in SSE2, so we keep the C-version:
  818. DST(0, 2) = AVG3(J, I, X);
  819. DST(0, 3) = AVG3(K, J, I);
  820. }
  821. static void VL4_SSE2(uint8_t* dst) { // Vertical-Left
  822. const __m128i one = _mm_set1_epi8(1);
  823. const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS));
  824. const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1);
  825. const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2);
  826. const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_);
  827. const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_);
  828. const __m128i avg3 = _mm_avg_epu8(avg1, avg2);
  829. const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one);
  830. const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_);
  831. const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_);
  832. const __m128i abbc = _mm_or_si128(ab, bc);
  833. const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
  834. const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
  835. const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
  836. WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
  837. WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
  838. WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
  839. WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
  840. // these two are hard to get and irregular
  841. DST(3, 2) = (extra_out >> 0) & 0xff;
  842. DST(3, 3) = (extra_out >> 8) & 0xff;
  843. }
  844. static void RD4_SSE2(uint8_t* dst) { // Down-right
  845. const __m128i one = _mm_set1_epi8(1);
  846. const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
  847. const __m128i ____XABCD = _mm_slli_si128(XABCD, 4);
  848. const uint32_t I = dst[-1 + 0 * BPS];
  849. const uint32_t J = dst[-1 + 1 * BPS];
  850. const uint32_t K = dst[-1 + 2 * BPS];
  851. const uint32_t L = dst[-1 + 3 * BPS];
  852. const __m128i LKJI_____ =
  853. _mm_cvtsi32_si128(L | (K << 8) | (J << 16) | (I << 24));
  854. const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD);
  855. const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1);
  856. const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2);
  857. const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD);
  858. const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
  859. const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
  860. const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
  861. WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
  862. WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
  863. WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
  864. WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
  865. }
  866. #undef DST
  867. #undef AVG3
  868. //------------------------------------------------------------------------------
  869. // Luma 16x16
  870. static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, int size) {
  871. const uint8_t* top = dst - BPS;
  872. const __m128i zero = _mm_setzero_si128();
  873. int y;
  874. if (size == 4) {
  875. const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top));
  876. const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
  877. for (y = 0; y < 4; ++y, dst += BPS) {
  878. const int val = dst[-1] - top[-1];
  879. const __m128i base = _mm_set1_epi16(val);
  880. const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
  881. WebPUint32ToMem(dst, _mm_cvtsi128_si32(out));
  882. }
  883. } else if (size == 8) {
  884. const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
  885. const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
  886. for (y = 0; y < 8; ++y, dst += BPS) {
  887. const int val = dst[-1] - top[-1];
  888. const __m128i base = _mm_set1_epi16(val);
  889. const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
  890. _mm_storel_epi64((__m128i*)dst, out);
  891. }
  892. } else {
  893. const __m128i top_values = _mm_loadu_si128((const __m128i*)top);
  894. const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero);
  895. const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero);
  896. for (y = 0; y < 16; ++y, dst += BPS) {
  897. const int val = dst[-1] - top[-1];
  898. const __m128i base = _mm_set1_epi16(val);
  899. const __m128i out_0 = _mm_add_epi16(base, top_base_0);
  900. const __m128i out_1 = _mm_add_epi16(base, top_base_1);
  901. const __m128i out = _mm_packus_epi16(out_0, out_1);
  902. _mm_storeu_si128((__m128i*)dst, out);
  903. }
  904. }
  905. }
  906. static void TM4_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 4); }
  907. static void TM8uv_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 8); }
  908. static void TM16_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 16); }
  909. static void VE16_SSE2(uint8_t* dst) {
  910. const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
  911. int j;
  912. for (j = 0; j < 16; ++j) {
  913. _mm_storeu_si128((__m128i*)(dst + j * BPS), top);
  914. }
  915. }
  916. static void HE16_SSE2(uint8_t* dst) { // horizontal
  917. int j;
  918. for (j = 16; j > 0; --j) {
  919. const __m128i values = _mm_set1_epi8(dst[-1]);
  920. _mm_storeu_si128((__m128i*)dst, values);
  921. dst += BPS;
  922. }
  923. }
  924. static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) {
  925. int j;
  926. const __m128i values = _mm_set1_epi8(v);
  927. for (j = 0; j < 16; ++j) {
  928. _mm_storeu_si128((__m128i*)(dst + j * BPS), values);
  929. }
  930. }
  931. static void DC16_SSE2(uint8_t* dst) { // DC
  932. const __m128i zero = _mm_setzero_si128();
  933. const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
  934. const __m128i sad8x2 = _mm_sad_epu8(top, zero);
  935. // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
  936. const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
  937. int left = 0;
  938. int j;
  939. for (j = 0; j < 16; ++j) {
  940. left += dst[-1 + j * BPS];
  941. }
  942. {
  943. const int DC = _mm_cvtsi128_si32(sum) + left + 16;
  944. Put16_SSE2(DC >> 5, dst);
  945. }
  946. }
  947. static void DC16NoTop_SSE2(uint8_t* dst) { // DC with top samples unavailable
  948. int DC = 8;
  949. int j;
  950. for (j = 0; j < 16; ++j) {
  951. DC += dst[-1 + j * BPS];
  952. }
  953. Put16_SSE2(DC >> 4, dst);
  954. }
  955. static void DC16NoLeft_SSE2(uint8_t* dst) { // DC with left samples unavailable
  956. const __m128i zero = _mm_setzero_si128();
  957. const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
  958. const __m128i sad8x2 = _mm_sad_epu8(top, zero);
  959. // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
  960. const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
  961. const int DC = _mm_cvtsi128_si32(sum) + 8;
  962. Put16_SSE2(DC >> 4, dst);
  963. }
  964. static void DC16NoTopLeft_SSE2(uint8_t* dst) { // DC with no top & left samples
  965. Put16_SSE2(0x80, dst);
  966. }
  967. //------------------------------------------------------------------------------
  968. // Chroma
  969. static void VE8uv_SSE2(uint8_t* dst) { // vertical
  970. int j;
  971. const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
  972. for (j = 0; j < 8; ++j) {
  973. _mm_storel_epi64((__m128i*)(dst + j * BPS), top);
  974. }
  975. }
  976. // helper for chroma-DC predictions
  977. static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) {
  978. int j;
  979. const __m128i values = _mm_set1_epi8(v);
  980. for (j = 0; j < 8; ++j) {
  981. _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
  982. }
  983. }
  984. static void DC8uv_SSE2(uint8_t* dst) { // DC
  985. const __m128i zero = _mm_setzero_si128();
  986. const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
  987. const __m128i sum = _mm_sad_epu8(top, zero);
  988. int left = 0;
  989. int j;
  990. for (j = 0; j < 8; ++j) {
  991. left += dst[-1 + j * BPS];
  992. }
  993. {
  994. const int DC = _mm_cvtsi128_si32(sum) + left + 8;
  995. Put8x8uv_SSE2(DC >> 4, dst);
  996. }
  997. }
  998. static void DC8uvNoLeft_SSE2(uint8_t* dst) { // DC with no left samples
  999. const __m128i zero = _mm_setzero_si128();
  1000. const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
  1001. const __m128i sum = _mm_sad_epu8(top, zero);
  1002. const int DC = _mm_cvtsi128_si32(sum) + 4;
  1003. Put8x8uv_SSE2(DC >> 3, dst);
  1004. }
  1005. static void DC8uvNoTop_SSE2(uint8_t* dst) { // DC with no top samples
  1006. int dc0 = 4;
  1007. int i;
  1008. for (i = 0; i < 8; ++i) {
  1009. dc0 += dst[-1 + i * BPS];
  1010. }
  1011. Put8x8uv_SSE2(dc0 >> 3, dst);
  1012. }
  1013. static void DC8uvNoTopLeft_SSE2(uint8_t* dst) { // DC with nothing
  1014. Put8x8uv_SSE2(0x80, dst);
  1015. }
  1016. //------------------------------------------------------------------------------
  1017. // Entry point
  1018. extern void VP8DspInitSSE2(void);
  1019. WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) {
  1020. VP8Transform = Transform_SSE2;
  1021. #if (USE_TRANSFORM_AC3 == 1)
  1022. VP8TransformAC3 = TransformAC3_SSE2;
  1023. #endif
  1024. VP8VFilter16 = VFilter16_SSE2;
  1025. VP8HFilter16 = HFilter16_SSE2;
  1026. VP8VFilter8 = VFilter8_SSE2;
  1027. VP8HFilter8 = HFilter8_SSE2;
  1028. VP8VFilter16i = VFilter16i_SSE2;
  1029. VP8HFilter16i = HFilter16i_SSE2;
  1030. VP8VFilter8i = VFilter8i_SSE2;
  1031. VP8HFilter8i = HFilter8i_SSE2;
  1032. VP8SimpleVFilter16 = SimpleVFilter16_SSE2;
  1033. VP8SimpleHFilter16 = SimpleHFilter16_SSE2;
  1034. VP8SimpleVFilter16i = SimpleVFilter16i_SSE2;
  1035. VP8SimpleHFilter16i = SimpleHFilter16i_SSE2;
  1036. VP8PredLuma4[1] = TM4_SSE2;
  1037. VP8PredLuma4[2] = VE4_SSE2;
  1038. VP8PredLuma4[4] = RD4_SSE2;
  1039. VP8PredLuma4[5] = VR4_SSE2;
  1040. VP8PredLuma4[6] = LD4_SSE2;
  1041. VP8PredLuma4[7] = VL4_SSE2;
  1042. VP8PredLuma16[0] = DC16_SSE2;
  1043. VP8PredLuma16[1] = TM16_SSE2;
  1044. VP8PredLuma16[2] = VE16_SSE2;
  1045. VP8PredLuma16[3] = HE16_SSE2;
  1046. VP8PredLuma16[4] = DC16NoTop_SSE2;
  1047. VP8PredLuma16[5] = DC16NoLeft_SSE2;
  1048. VP8PredLuma16[6] = DC16NoTopLeft_SSE2;
  1049. VP8PredChroma8[0] = DC8uv_SSE2;
  1050. VP8PredChroma8[1] = TM8uv_SSE2;
  1051. VP8PredChroma8[2] = VE8uv_SSE2;
  1052. VP8PredChroma8[4] = DC8uvNoTop_SSE2;
  1053. VP8PredChroma8[5] = DC8uvNoLeft_SSE2;
  1054. VP8PredChroma8[6] = DC8uvNoTopLeft_SSE2;
  1055. }
  1056. #else // !WEBP_USE_SSE2
  1057. WEBP_DSP_INIT_STUB(VP8DspInitSSE2)
  1058. #endif // WEBP_USE_SSE2