GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 59 / 0 / 59
Functions: 100.0% 1 / 0 / 1
Branches: 100.0% 12 / 0 / 12

filters/intel/text-overlay_sse.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35 #include <avisynth.h>
36 #include <avs/minmax.h>
37 #define __STDC_FORMAT_MACROS
38 #include <inttypes.h>
39
40 // Intrinsics base header + really required extension headers
41 #if defined(_MSC_VER)
42 #include <intrin.h> // MSVC
43 #else
44 #include <x86intrin.h> // GCC/MinGW/Clang/LLVM
45 #endif
46
47
48 8 void compare_sse2(uint32_t mask, int increment,
49 const BYTE * f1ptr, int pitch1,
50 const BYTE * f2ptr, int pitch2,
51 int rowsize, int height,
52 int64_t &SAD_sum, int64_t &SD_sum, int &pos_D, int &neg_D, double &SSD_sum)
53 {
54 // rowsize multiple of 16 for YUV Planar, RGB32 and YUY2; 12 for RGB24
55 // increment must be 3 for RGB24 and 4 for others
56
57 8 int64_t issd = 0;
58 // using 32 bit partial sums in sad_vector/sd_vector
59 // for large frames (4K) these would overflow for the whole frame
60 // so we flush them per row
61 8 int64_t isad = 0;
62 8 int64_t isd = 0;
63 8 __m128i positive_diff = _mm_setzero_si128();
64 8 __m128i negative_diff = _mm_setzero_si128();
65 8 __m128i zero = _mm_setzero_si128();
66
67 8 __m128i mask64 = _mm_set_epi32(0, 0, 0, mask);
68
2/2
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 16 taken 6 times.
8 if (increment == 3) {
69 2 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 3));
70 4 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 6));
71 } else {
72 6 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 4));
73 12 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 8));
74 }
75
76
77
78
2/2
✓ Branch 88 → 22 taken 2194 times.
✓ Branch 88 → 89 taken 8 times.
2202 for (int y = 0; y < height; ++y) {
79 2194 __m128i row_ssd = _mm_setzero_si128(); // sum of squared differences (row_SSD)
80 2194 __m128i sad_vector = _mm_setzero_si128(); //sum of absolute differences
81 2194 __m128i sd_vector = _mm_setzero_si128(); // sum of differences
82
83
2/2
✓ Branch 72 → 29 taken 2073717 times.
✓ Branch 72 → 73 taken 2194 times.
2075911 for (int x = 0; x < rowsize; x+=increment*4) {
84 2073717 __m128i src1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(f1ptr+x));
85 4147434 __m128i src2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(f2ptr+x));
86
87 2073717 src1 = _mm_and_si128(src1, mask64);
88 2073717 src2 = _mm_and_si128(src2, mask64);
89
90 2073717 __m128i diff_1_minus_2 = _mm_subs_epu8(src1, src2);
91 2073717 __m128i diff_2_minus_1 = _mm_subs_epu8(src2, src1);
92
93 2073717 positive_diff = _mm_max_epu8(positive_diff, diff_1_minus_2);
94 2073717 negative_diff = _mm_max_epu8(negative_diff, diff_2_minus_1);
95
96 2073717 __m128i absdiff1 = _mm_sad_epu8(diff_1_minus_2, zero);
97 2073717 __m128i absdiff2 = _mm_sad_epu8(diff_2_minus_1, zero);
98
99 2073717 sad_vector = _mm_add_epi32(sad_vector, absdiff1);
100 2073717 sad_vector = _mm_add_epi32(sad_vector, absdiff2);
101
102 2073717 sd_vector = _mm_add_epi32(sd_vector, absdiff1);
103 2073717 sd_vector = _mm_sub_epi32(sd_vector, absdiff2);
104
105 2073717 __m128i ssd = _mm_or_si128(diff_1_minus_2, diff_2_minus_1);
106 2073717 __m128i ssd_lo = _mm_unpacklo_epi8(ssd, zero);
107 2073717 __m128i ssd_hi = _mm_unpackhi_epi8(ssd, zero);
108 2073717 ssd_lo = _mm_madd_epi16(ssd_lo, ssd_lo);
109 2073717 ssd_hi = _mm_madd_epi16(ssd_hi, ssd_hi);
110 2073717 row_ssd = _mm_add_epi32(row_ssd, ssd_lo);
111 2073717 row_ssd = _mm_add_epi32(row_ssd, ssd_hi);
112 }
113
114 2194 f1ptr += pitch1;
115 2194 f2ptr += pitch2;
116
117 2194 __m128i tmp = _mm_srli_si128(row_ssd, 8);
118 2194 row_ssd = _mm_add_epi32(row_ssd, tmp);
119 2194 tmp = _mm_srli_si128(row_ssd, 4);
120 2194 row_ssd = _mm_add_epi32(row_ssd, tmp);
121
122 2194 issd += _mm_cvtsi128_si32(row_ssd);
123
124 2194 isad += _mm_cvtsi128_si32(sad_vector);
125 4388 isad += _mm_cvtsi128_si32(_mm_srli_si128(sad_vector, 8));
126 2194 isd += _mm_cvtsi128_si32(sd_vector);
127 4388 isd += _mm_cvtsi128_si32(_mm_srli_si128(sd_vector, 8));
128 }
129
130 8 SAD_sum += isad;
131 8 SD_sum += isd;
132
133 BYTE posdiff_tmp[16];
134 BYTE negdiff_tmp[16];
135 _mm_store_si128(reinterpret_cast<__m128i*>(posdiff_tmp), positive_diff);
136 _mm_store_si128(reinterpret_cast<__m128i*>(negdiff_tmp), negative_diff);
137
138 8 SSD_sum += (double)issd;
139
140 8 neg_D = -neg_D; // 160801! false neg_D fix for isse
141
142
2/2
✓ Branch 103 → 92 taken 120 times.
✓ Branch 103 → 104 taken 8 times.
128 for (int i = 0; i < increment*4; ++i) {
143
2/2
✓ Branch 92 → 93 taken 82 times.
✓ Branch 92 → 94 taken 38 times.
120 pos_D = max(pos_D, (int)(posdiff_tmp[i]));
144
2/2
✓ Branch 97 → 98 taken 80 times.
✓ Branch 97 → 99 taken 40 times.
240 neg_D = max(neg_D, (int)(negdiff_tmp[i]));
145 }
146
147 8 neg_D = -neg_D;
148 8 }
149
150 #ifdef X86_32
151
152 void compare_isse(uint32_t mask, int increment,
153 const BYTE * f1ptr, int pitch1,
154 const BYTE * f2ptr, int pitch2,
155 int rowsize, int height,
156 int64_t &SAD_sum, int64_t &SD_sum, int &pos_D, int &neg_D, double &SSD_sum)
157 {
158 // rowsize multiple of 8 for YUV Planar, RGB32 and YUY2; 6 for RGB24
159 // increment must be 3 for RGB24 and 4 for others
160
161 int64_t issd = 0;
162 // using 32 bit partial sums in sad_vector/sd_vector
163 // for large frames (4K) these would overflow for the whole frame
164 // so we flush them per row
165 int64_t isad = 0, isd = 0;
166 __m64 positive_diff = _mm_setzero_si64();
167 __m64 negative_diff = _mm_setzero_si64();
168 __m64 zero = _mm_setzero_si64();
169
170 __m64 mask64 = _mm_set_pi32(0, mask);
171 mask64 = _mm_or_si64(mask64, _mm_slli_si64(mask64, increment*8));
172
173
174 for (int y = 0; y < height; ++y) {
175 __m64 row_ssd = _mm_setzero_si64(); // sum of squared differences (row_SSD)
176 __m64 sad_vector = _mm_setzero_si64(); //sum of absolute differences
177 __m64 sd_vector = _mm_setzero_si64(); // sum of differences
178
179 for (int x = 0; x < rowsize; x+=increment*2) {
180 __m64 src1 = *reinterpret_cast<const __m64*>(f1ptr+x);
181 __m64 src2 = *reinterpret_cast<const __m64*>(f2ptr+x);
182
183 src1 = _mm_and_si64(src1, mask64);
184 src2 = _mm_and_si64(src2, mask64);
185
186 __m64 diff_1_minus_2 = _mm_subs_pu8(src1, src2);
187 __m64 diff_2_minus_1 = _mm_subs_pu8(src2, src1);
188
189 positive_diff = _mm_max_pu8(positive_diff, diff_1_minus_2);
190 negative_diff = _mm_max_pu8(negative_diff, diff_2_minus_1);
191
192 __m64 absdiff1 = _mm_sad_pu8(diff_1_minus_2, zero);
193 __m64 absdiff2 = _mm_sad_pu8(diff_2_minus_1, zero);
194
195 sad_vector = _mm_add_pi32(sad_vector, absdiff1);
196 sad_vector = _mm_add_pi32(sad_vector, absdiff2);
197
198 sd_vector = _mm_add_pi32(sd_vector, absdiff1);
199 sd_vector = _mm_sub_pi32(sd_vector, absdiff2);
200
201 __m64 ssd = _mm_or_si64(diff_1_minus_2, diff_2_minus_1);
202 __m64 ssd_lo = _mm_unpacklo_pi8(ssd, zero);
203 __m64 ssd_hi = _mm_unpackhi_pi8(ssd, zero);
204 ssd_lo = _mm_madd_pi16(ssd_lo, ssd_lo);
205 ssd_hi = _mm_madd_pi16(ssd_hi, ssd_hi);
206 row_ssd = _mm_add_pi32(row_ssd, ssd_lo);
207 row_ssd = _mm_add_pi32(row_ssd, ssd_hi);
208 }
209
210 f1ptr += pitch1;
211 f2ptr += pitch2;
212
213 __m64 tmp = _mm_unpackhi_pi32(row_ssd, zero);
214 row_ssd = _mm_add_pi32(row_ssd, tmp);
215
216 issd += _mm_cvtsi64_si32(row_ssd);
217
218 isad += _mm_cvtsi64_si32(sad_vector);
219 isd += _mm_cvtsi64_si32(sd_vector);
220 }
221
222 SAD_sum += isad;
223 SD_sum += isd;
224
225 BYTE posdiff_tmp[8];
226 BYTE negdiff_tmp[8];
227 *reinterpret_cast<__m64*>(posdiff_tmp) = positive_diff;
228 *reinterpret_cast<__m64*>(negdiff_tmp) = negative_diff;
229 _mm_empty();
230
231 SSD_sum += (double)issd;
232
233 neg_D = -neg_D; // 160801! false neg_D fix for isse
234
235 for (int i = 0; i < increment*2; ++i) {
236 pos_D = max(pos_D, (int)(posdiff_tmp[i]));
237 neg_D = max(neg_D, (int)(negdiff_tmp[i]));
238 }
239
240 neg_D = -neg_D;
241 }
242
243 #endif
244
245
246
247