GCC Code Coverage Report


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

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 int &SAD_sum, int &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 8 __m128i sad_vector = _mm_setzero_si128(); //sum of absolute differences
59 8 __m128i sd_vector = _mm_setzero_si128(); // sum of differences
60 8 __m128i positive_diff = _mm_setzero_si128();
61 8 __m128i negative_diff = _mm_setzero_si128();
62 8 __m128i zero = _mm_setzero_si128();
63
64 8 __m128i mask64 = _mm_set_epi32(0, 0, 0, mask);
65
2/2
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 20 taken 6 times.
8 if (increment == 3) {
66 2 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 3));
67 4 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 6));
68 } else {
69 6 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 4));
70 12 mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 8));
71 }
72
73
74
75
2/2
✓ Branch 80 → 26 taken 2194 times.
✓ Branch 80 → 81 taken 8 times.
2202 for (int y = 0; y < height; ++y) {
76 2194 __m128i row_ssd = _mm_setzero_si128(); // sum of squared differences (row_SSD)
77
78
2/2
✓ Branch 72 → 29 taken 2073717 times.
✓ Branch 72 → 73 taken 2194 times.
2075911 for (int x = 0; x < rowsize; x+=increment*4) {
79 2073717 __m128i src1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(f1ptr+x));
80 4147434 __m128i src2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(f2ptr+x));
81
82 2073717 src1 = _mm_and_si128(src1, mask64);
83 2073717 src2 = _mm_and_si128(src2, mask64);
84
85 2073717 __m128i diff_1_minus_2 = _mm_subs_epu8(src1, src2);
86 2073717 __m128i diff_2_minus_1 = _mm_subs_epu8(src2, src1);
87
88 2073717 positive_diff = _mm_max_epu8(positive_diff, diff_1_minus_2);
89 2073717 negative_diff = _mm_max_epu8(negative_diff, diff_2_minus_1);
90
91 2073717 __m128i absdiff1 = _mm_sad_epu8(diff_1_minus_2, zero);
92 2073717 __m128i absdiff2 = _mm_sad_epu8(diff_2_minus_1, zero);
93
94 2073717 sad_vector = _mm_add_epi32(sad_vector, absdiff1);
95 2073717 sad_vector = _mm_add_epi32(sad_vector, absdiff2);
96
97 2073717 sd_vector = _mm_add_epi32(sd_vector, absdiff1);
98 2073717 sd_vector = _mm_sub_epi32(sd_vector, absdiff2);
99
100 2073717 __m128i ssd = _mm_or_si128(diff_1_minus_2, diff_2_minus_1);
101 2073717 __m128i ssd_lo = _mm_unpacklo_epi8(ssd, zero);
102 2073717 __m128i ssd_hi = _mm_unpackhi_epi8(ssd, zero);
103 2073717 ssd_lo = _mm_madd_epi16(ssd_lo, ssd_lo);
104 2073717 ssd_hi = _mm_madd_epi16(ssd_hi, ssd_hi);
105 2073717 row_ssd = _mm_add_epi32(row_ssd, ssd_lo);
106 2073717 row_ssd = _mm_add_epi32(row_ssd, ssd_hi);
107 }
108
109 2194 f1ptr += pitch1;
110 2194 f2ptr += pitch2;
111
112 2194 __m128i tmp = _mm_srli_si128(row_ssd, 8);
113 2194 row_ssd = _mm_add_epi32(row_ssd, tmp);
114 2194 tmp = _mm_srli_si128(row_ssd, 4);
115 2194 row_ssd = _mm_add_epi32(row_ssd, tmp);
116
117 2194 issd += _mm_cvtsi128_si32(row_ssd);
118 }
119
120 8 SAD_sum += _mm_cvtsi128_si32(sad_vector);
121 16 SAD_sum += _mm_cvtsi128_si32(_mm_srli_si128(sad_vector, 8));
122 8 SD_sum += _mm_cvtsi128_si32(sd_vector);
123 16 SD_sum += _mm_cvtsi128_si32(_mm_srli_si128(sd_vector, 8));
124
125 BYTE posdiff_tmp[16];
126 BYTE negdiff_tmp[16];
127 _mm_store_si128(reinterpret_cast<__m128i*>(posdiff_tmp), positive_diff);
128 _mm_store_si128(reinterpret_cast<__m128i*>(negdiff_tmp), negative_diff);
129
130 8 SSD_sum += (double)issd;
131
132 8 neg_D = -neg_D; // 160801! false neg_D fix for isse
133
134
2/2
✓ Branch 95 → 92 taken 120 times.
✓ Branch 95 → 96 taken 8 times.
128 for (int i = 0; i < increment*4; ++i) {
135 120 pos_D = max(pos_D, (int)(posdiff_tmp[i]));
136 120 neg_D = max(neg_D, (int)(negdiff_tmp[i]));
137 }
138
139 8 neg_D = -neg_D;
140 8 }
141
142 #ifdef X86_32
143
144 void compare_isse(uint32_t mask, int increment,
145 const BYTE * f1ptr, int pitch1,
146 const BYTE * f2ptr, int pitch2,
147 int rowsize, int height,
148 int &SAD_sum, int &SD_sum, int &pos_D, int &neg_D, double &SSD_sum)
149 {
150 // rowsize multiple of 8 for YUV Planar, RGB32 and YUY2; 6 for RGB24
151 // increment must be 3 for RGB24 and 4 for others
152
153 int64_t issd = 0;
154 __m64 sad_vector = _mm_setzero_si64(); //sum of absolute differences
155 __m64 sd_vector = _mm_setzero_si64(); // sum of differences
156 __m64 positive_diff = _mm_setzero_si64();
157 __m64 negative_diff = _mm_setzero_si64();
158 __m64 zero = _mm_setzero_si64();
159
160 __m64 mask64 = _mm_set_pi32(0, mask);
161 mask64 = _mm_or_si64(mask64, _mm_slli_si64(mask64, increment*8));
162
163
164 for (int y = 0; y < height; ++y) {
165 __m64 row_ssd = _mm_setzero_si64(); // sum of squared differences (row_SSD)
166
167 for (int x = 0; x < rowsize; x+=increment*2) {
168 __m64 src1 = *reinterpret_cast<const __m64*>(f1ptr+x);
169 __m64 src2 = *reinterpret_cast<const __m64*>(f2ptr+x);
170
171 src1 = _mm_and_si64(src1, mask64);
172 src2 = _mm_and_si64(src2, mask64);
173
174 __m64 diff_1_minus_2 = _mm_subs_pu8(src1, src2);
175 __m64 diff_2_minus_1 = _mm_subs_pu8(src2, src1);
176
177 positive_diff = _mm_max_pu8(positive_diff, diff_1_minus_2);
178 negative_diff = _mm_max_pu8(negative_diff, diff_2_minus_1);
179
180 __m64 absdiff1 = _mm_sad_pu8(diff_1_minus_2, zero);
181 __m64 absdiff2 = _mm_sad_pu8(diff_2_minus_1, zero);
182
183 sad_vector = _mm_add_pi32(sad_vector, absdiff1);
184 sad_vector = _mm_add_pi32(sad_vector, absdiff2);
185
186 sd_vector = _mm_add_pi32(sd_vector, absdiff1);
187 sd_vector = _mm_sub_pi32(sd_vector, absdiff2);
188
189 __m64 ssd = _mm_or_si64(diff_1_minus_2, diff_2_minus_1);
190 __m64 ssd_lo = _mm_unpacklo_pi8(ssd, zero);
191 __m64 ssd_hi = _mm_unpackhi_pi8(ssd, zero);
192 ssd_lo = _mm_madd_pi16(ssd_lo, ssd_lo);
193 ssd_hi = _mm_madd_pi16(ssd_hi, ssd_hi);
194 row_ssd = _mm_add_pi32(row_ssd, ssd_lo);
195 row_ssd = _mm_add_pi32(row_ssd, ssd_hi);
196 }
197
198 f1ptr += pitch1;
199 f2ptr += pitch2;
200
201 __m64 tmp = _mm_unpackhi_pi32(row_ssd, zero);
202 row_ssd = _mm_add_pi32(row_ssd, tmp);
203
204 issd += _mm_cvtsi64_si32(row_ssd);
205 }
206
207 SAD_sum += _mm_cvtsi64_si32(sad_vector);
208 SD_sum += _mm_cvtsi64_si32(sd_vector);
209
210 BYTE posdiff_tmp[8];
211 BYTE negdiff_tmp[8];
212 *reinterpret_cast<__m64*>(posdiff_tmp) = positive_diff;
213 *reinterpret_cast<__m64*>(negdiff_tmp) = negative_diff;
214 _mm_empty();
215
216 SSD_sum += (double)issd;
217
218 neg_D = -neg_D; // 160801! false neg_D fix for isse
219
220 for (int i = 0; i < increment*2; ++i) {
221 pos_D = max(pos_D, (int)(posdiff_tmp[i]));
222 neg_D = max(neg_D, (int)(negdiff_tmp[i]));
223 }
224
225 neg_D = -neg_D;
226 }
227
228 #endif
229
230
231
232