GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 67.1% 267 / 0 / 398
Functions: 68.2% 15 / 0 / 22
Branches: 58.4% 104 / 0 / 178

filters/overlay/intel/blend_common_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 // Overlay (c) 2003, 2004 by Klaus Post
36
37 #include <avisynth.h>
38
39 #include "blend_common_sse.h"
40 #include "../blend_common.h"
41 #include "../../../core/internal.h"
42
43 // Intrinsics base header + really required extension headers
44 #if defined(_MSC_VER)
45 #include <intrin.h> // MSVC
46 #else
47 #include <x86intrin.h> // GCC/MinGW/Clang/LLVM
48 #endif
49 #include <smmintrin.h> // SSE4.1
50
51 #include <stdint.h>
52 #include <type_traits>
53 #include <vector>
54
55 /********************************
56 ********* Blend Opaque *********
57 ** Use for Lighten and Darken **
58 ********************************/
59
60 #ifdef X86_32
61 AVS_FORCEINLINE __m64 overlay_blend_opaque_mmx_core(const __m64& p1, const __m64& p2, const __m64& mask) {
62 // return (mask) ? p2 : p1;
63 __m64 r1 = _mm_andnot_si64(mask, p1);
64 __m64 r2 = _mm_and_si64 (mask, p2);
65 return _mm_or_si64(r1, r2);
66 }
67 #endif
68
69 AVS_FORCEINLINE __m128i overlay_blend_opaque_sse2_core(const __m128i& p1, const __m128i& p2, const __m128i& mask) {
70 // return (mask) ? p2 : p1;
71 108 __m128i r1 = _mm_andnot_si128(mask, p1);
72 108 __m128i r2 = _mm_and_si128 (mask, p2);
73 54 return _mm_or_si128(r1, r2);
74 }
75
76 // simd_magic_div_32, blend8_masked_sse41_row, blend16_masked_sse41_row, masked_merge_sse41_impl
77 // (implementation-include, no guards — each TU gets its own compiled copy)
78 #include "masked_merge_sse41_impl.hpp"
79
80 void masked_merge_float_sse2(BYTE* p1, const BYTE* p2, const BYTE* mask,
81 int p1_pitch, int p2_pitch, int mask_pitch,
82 int width, int height, float opacity_f)
83 {
84 const int realwidth = width * sizeof(float);
85 const int wMod16 = (realwidth / 16) * 16;
86 const __m128 opacity_v = _mm_set1_ps(opacity_f);
87
88 for (int y = 0; y < height; y++) {
89 for (int x = 0; x < wMod16; x += 16) {
90 const __m128 p1_f = _mm_loadu_ps(reinterpret_cast<const float*>(p1 + x));
91 const __m128 p2_f = _mm_loadu_ps(reinterpret_cast<const float*>(p2 + x));
92 const __m128 mask_f = _mm_mul_ps(_mm_loadu_ps(reinterpret_cast<const float*>(mask + x)), opacity_v);
93 // p1*(1-m) + p2*m = p1 + (p2-p1)*m
94 _mm_storeu_ps(reinterpret_cast<float*>(p1 + x),
95 _mm_add_ps(p1_f, _mm_mul_ps(_mm_sub_ps(p2_f, p1_f), mask_f)));
96 }
97 for (int x = wMod16 / (int)sizeof(float); x < width; x++) {
98 const float m = reinterpret_cast<const float*>(mask)[x] * opacity_f;
99 const float a = reinterpret_cast<float*>(p1)[x];
100 const float b = reinterpret_cast<const float*>(p2)[x];
101 reinterpret_cast<float*>(p1)[x] = a + (b - a) * m;
102 }
103 p1 += p1_pitch;
104 p2 += p2_pitch;
105 mask += mask_pitch;
106 }
107 }
108
109
110 /***************************************
111 ********* Mode: Lighten/Darken ********
112 ***************************************/
113
114 typedef __m128i (OverlaySseBlendOpaque)(const __m128i&, const __m128i&, const __m128i&);
115 typedef __m128i (OverlaySseCompare)(const __m128i&, const __m128i&, const __m128i&);
116 #ifdef X86_32
117 typedef __m64 (OverlayMmxCompare)(const __m64&, const __m64&, const __m64&);
118 #endif
119
120 typedef int (OverlayCCompare)(BYTE, BYTE);
121
122
123 #ifdef X86_32
124 template<OverlayMmxCompare compare, OverlayCCompare compare_c>
125 AVS_FORCEINLINE void overlay_darklighten_mmx(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
126 __m64 zero = _mm_setzero_si64();
127
128 int wMod8 = (width/8) * 8;
129
130 for (int y = 0; y < height; y++) {
131 for (int x = 0; x < wMod8; x+=8) {
132 // Load Y Plane
133 __m64 p1_y = *(reinterpret_cast<const __m64*>(p1Y+x));
134 __m64 p2_y = *(reinterpret_cast<const __m64*>(p2Y+x));
135
136 // Compare
137 __m64 cmp_result = compare(p1_y, p2_y, zero);
138
139 // Process U Plane
140 __m64 result_y = overlay_blend_opaque_mmx_core(p1_y, p2_y, cmp_result);
141 *reinterpret_cast<__m64*>(p1Y+x) = result_y;
142
143 // Process U plane
144 __m64 p1_u = *(reinterpret_cast<const __m64*>(p1U+x));
145 __m64 p2_u = *(reinterpret_cast<const __m64*>(p2U+x));
146
147 __m64 result_u = overlay_blend_opaque_mmx_core(p1_u, p2_u, cmp_result);
148 *reinterpret_cast<__m64*>(p1U+x) = result_u;
149
150 // Process V plane
151 __m64 p1_v = *(reinterpret_cast<const __m64*>(p1V+x));
152 __m64 p2_v = *(reinterpret_cast<const __m64*>(p2V+x));
153
154 __m64 result_v = overlay_blend_opaque_mmx_core(p1_v, p2_v, cmp_result);
155 *reinterpret_cast<__m64*>(p1V+x) = result_v;
156 }
157
158 // Leftover value
159 for (int x = wMod8; x < width; x++) {
160 int mask = compare_c(p1Y[x], p2Y[x]);
161 p1Y[x] = overlay_blend_opaque_c_core<uint8_t>(p1Y[x], p2Y[x], mask);
162 p1U[x] = overlay_blend_opaque_c_core<uint8_t>(p1U[x], p2U[x], mask);
163 p1V[x] = overlay_blend_opaque_c_core<uint8_t>(p1V[x], p2V[x], mask);
164 }
165
166 p1Y += p1_pitch;
167 p1U += p1_pitch;
168 p1V += p1_pitch;
169
170 p2Y += p2_pitch;
171 p2U += p2_pitch;
172 p2V += p2_pitch;
173 }
174
175 _mm_empty();
176 }
177 #endif
178
179 template <OverlaySseCompare compare, OverlayCCompare compare_c>
180 4 void overlay_darklighten_sse2(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
181 4 __m128i zero = _mm_setzero_si128();
182
183 4 int wMod16 = (width/16) * 16;
184
185
4/4
void overlay_darklighten_sse2<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 74 → 5 taken 9 times.
✓ Branch 74 → 75 taken 2 times.
void overlay_darklighten_sse2<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 74 → 5 taken 9 times.
✓ Branch 74 → 75 taken 2 times.
22 for (int y = 0; y < height; y++) {
186
4/4
void overlay_darklighten_sse2<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 52 → 6 taken 9 times.
✓ Branch 52 → 53 taken 9 times.
void overlay_darklighten_sse2<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 52 → 6 taken 9 times.
✓ Branch 52 → 53 taken 9 times.
36 for (int x = 0; x < wMod16; x+=16) {
187 // Load Y Plane
188 18 __m128i p1_y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1Y+x));
189 18 __m128i p2_y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2Y+x));
190
191 // Compare
192 18 __m128i cmp_result = compare(p1_y, p2_y, zero);
193
194 // Process U Plane
195 18 __m128i result_y = overlay_blend_opaque_sse2_core(p1_y, p2_y, cmp_result);
196 18 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1Y+x), result_y);
197
198 // Process U plane
199 18 __m128i p1_u = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1U+x));
200 36 __m128i p2_u = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2U+x));
201
202 18 __m128i result_u = overlay_blend_opaque_sse2_core(p1_u, p2_u, cmp_result);
203 18 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1U+x), result_u);
204
205 // Process V plane
206 18 __m128i p1_v = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1V+x));
207 36 __m128i p2_v = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2V+x));
208
209 18 __m128i result_v = overlay_blend_opaque_sse2_core(p1_v, p2_v, cmp_result);
210 18 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1V+x), result_v);
211 }
212
213 // Leftover value
214
4/4
void overlay_darklighten_sse2<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 72 → 54 taken 93 times.
✓ Branch 72 → 73 taken 9 times.
void overlay_darklighten_sse2<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 72 → 54 taken 93 times.
✓ Branch 72 → 73 taken 9 times.
204 for (int x = wMod16; x < width; x++) {
215 186 int mask = compare_c(p1Y[x], p2Y[x]);
216 372 p1Y[x] = overlay_blend_opaque_c_core<uint8_t>(p1Y[x], p2Y[x], mask);
217
4/4
void overlay_darklighten_sse2<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 61 → 62 taken 48 times.
✓ Branch 61 → 63 taken 45 times.
void overlay_darklighten_sse2<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 61 → 62 taken 52 times.
✓ Branch 61 → 63 taken 41 times.
186 p1U[x] = overlay_blend_opaque_c_core<uint8_t>(p1U[x], p2U[x], mask);
218
4/4
void overlay_darklighten_sse2<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 66 → 67 taken 48 times.
✓ Branch 66 → 68 taken 45 times.
void overlay_darklighten_sse2<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 66 → 67 taken 52 times.
✓ Branch 66 → 68 taken 41 times.
372 p1V[x] = overlay_blend_opaque_c_core<uint8_t>(p1V[x], p2V[x], mask);
219 }
220
221 18 p1Y += p1_pitch;
222 18 p1U += p1_pitch;
223 18 p1V += p1_pitch;
224
225 18 p2Y += p2_pitch;
226 18 p2U += p2_pitch;
227 18 p2V += p2_pitch;
228 }
229 4 }
230
231 template <OverlaySseCompare compare, OverlayCCompare compare_c>
232 #if defined(GCC) || defined(CLANG)
233 __attribute__((__target__("sse4.1")))
234 #endif
235 8 void overlay_darklighten_sse41(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height)
236 {
237 8 __m128i zero = _mm_setzero_si128();
238
239 8 int wMod16 = (width / 16) * 16;
240
241
4/4
void overlay_darklighten_sse41<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 56 → 5 taken 13 times.
✓ Branch 56 → 57 taken 4 times.
void overlay_darklighten_sse41<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 56 → 5 taken 13 times.
✓ Branch 56 → 57 taken 4 times.
34 for (int y = 0; y < height; y++) {
242
4/4
void overlay_darklighten_sse41<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 34 → 6 taken 9 times.
✓ Branch 34 → 35 taken 13 times.
void overlay_darklighten_sse41<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 34 → 6 taken 9 times.
✓ Branch 34 → 35 taken 13 times.
44 for (int x = 0; x < wMod16; x += 16) {
243 // Load Y Plane
244 18 __m128i p1_y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1Y + x));
245 18 __m128i p2_y = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2Y + x));
246
247 // Compare
248 __m128i cmp_result = compare(p1_y, p2_y, zero);
249
250 // Process Y Plane
251 36 __m128i result_y = _mm_blendv_epi8(p1_y, p2_y, cmp_result); // SSE4.1
252 18 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1Y + x), result_y);
253
254 // Process U plane
255 18 __m128i p1_u = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1U + x));
256 36 __m128i p2_u = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2U + x));
257
258 18 __m128i result_u = _mm_blendv_epi8(p1_u, p2_u, cmp_result);
259 18 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1U + x), result_u);
260
261 // Process V plane
262 18 __m128i p1_v = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1V + x));
263 36 __m128i p2_v = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2V + x));
264
265 18 __m128i result_v = _mm_blendv_epi8(p1_v, p2_v, cmp_result);
266 18 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1V + x), result_v);
267 }
268
269 // Leftover value
270
4/4
void overlay_darklighten_sse41<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 54 → 36 taken 109 times.
✓ Branch 54 → 55 taken 13 times.
void overlay_darklighten_sse41<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 54 → 36 taken 109 times.
✓ Branch 54 → 55 taken 13 times.
244 for (int x = wMod16; x < width; x++) {
271 218 int mask = compare_c(p1Y[x], p2Y[x]);
272 436 p1Y[x] = overlay_blend_opaque_c_core<uint8_t>(p1Y[x], p2Y[x], mask);
273
4/4
void overlay_darklighten_sse41<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 43 → 44 taken 64 times.
✓ Branch 43 → 45 taken 45 times.
void overlay_darklighten_sse41<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 43 → 44 taken 68 times.
✓ Branch 43 → 45 taken 41 times.
218 p1U[x] = overlay_blend_opaque_c_core<uint8_t>(p1U[x], p2U[x], mask);
274
4/4
void overlay_darklighten_sse41<&(overlay_darken_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(overlay_darken_c_cmp(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 48 → 49 taken 64 times.
✓ Branch 48 → 50 taken 45 times.
void overlay_darklighten_sse41<&(overlay_lighten_sse_cmp(long long __vector(2) const&, long long __vector(2) const&, long long __vector(2) const&)), &(int overlay_lighten_c_cmp<unsigned char>(unsigned char, unsigned char))>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int):
✓ Branch 48 → 49 taken 68 times.
✓ Branch 48 → 50 taken 41 times.
436 p1V[x] = overlay_blend_opaque_c_core<uint8_t>(p1V[x], p2V[x], mask);
275 }
276
277 26 p1Y += p1_pitch;
278 26 p1U += p1_pitch;
279 26 p1V += p1_pitch;
280
281 26 p2Y += p2_pitch;
282 26 p2U += p2_pitch;
283 26 p2V += p2_pitch;
284 }
285 8 }
286
287 // Compare functions for lighten and darken mode
288 AVS_FORCEINLINE static int overlay_darken_c_cmp(BYTE p1, BYTE p2) {
289 202 return p2 <= p1;
290 }
291
292 #ifdef X86_32
293 AVS_FORCEINLINE __m64 overlay_darken_mmx_cmp(const __m64& p1, const __m64& p2, const __m64& zero) {
294 __m64 diff = _mm_subs_pu8(p2, p1);
295 return _mm_cmpeq_pi8(diff, zero);
296 }
297 #endif
298
299 AVS_FORCEINLINE __m128i overlay_darken_sse_cmp(const __m128i& p1, const __m128i& p2, const __m128i& zero) {
300 18 __m128i diff = _mm_subs_epu8(p2, p1);
301 36 return _mm_cmpeq_epi8(diff, zero);
302 }
303
304 template<typename pixel_t>
305 AVS_FORCEINLINE int overlay_lighten_c_cmp(pixel_t p1, pixel_t p2) {
306 202 return p2 >= p1;
307 }
308
309 #ifdef X86_32
310 AVS_FORCEINLINE __m64 overlay_lighten_mmx_cmp(const __m64& p1, const __m64& p2, const __m64& zero) {
311 __m64 diff = _mm_subs_pu8(p1, p2);
312 return _mm_cmpeq_pi8(diff, zero);
313 }
314 #endif
315
316 AVS_FORCEINLINE __m128i overlay_lighten_sse_cmp(const __m128i& p1, const __m128i& p2, const __m128i& zero) {
317 18 __m128i diff = _mm_subs_epu8(p1, p2);
318 36 return _mm_cmpeq_epi8(diff, zero);
319 }
320
321 #ifdef X86_32
322 void overlay_darken_mmx(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
323 overlay_darklighten_mmx<overlay_darken_mmx_cmp, overlay_darken_c_cmp>(p1Y, p1U, p1V, p2Y, p2U, p2V, p1_pitch, p2_pitch, width, height);
324 }
325 void overlay_lighten_mmx(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
326 overlay_darklighten_mmx<overlay_lighten_mmx_cmp, overlay_lighten_c_cmp>(p1Y, p1U, p1V, p2Y, p2U, p2V, p1_pitch, p2_pitch, width, height);
327 }
328 #endif
329
330 2 void overlay_darken_sse2(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
331
2/2
✓ Branch 56 → 57 taken 48 times.
✓ Branch 56 → 58 taken 45 times.
197 overlay_darklighten_sse2<overlay_darken_sse_cmp, overlay_darken_c_cmp>(p1Y, p1U, p1V, p2Y, p2U, p2V, p1_pitch, p2_pitch, width, height);
332 2 }
333 2 void overlay_lighten_sse2(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
334
2/2
✓ Branch 56 → 57 taken 52 times.
✓ Branch 56 → 58 taken 41 times.
197 overlay_darklighten_sse2<overlay_lighten_sse_cmp, overlay_lighten_c_cmp>(p1Y, p1U, p1V, p2Y, p2U, p2V, p1_pitch, p2_pitch, width, height);
335 2 }
336
337 4 void overlay_darken_sse41(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
338
2/2
✓ Branch 38 → 39 taken 64 times.
✓ Branch 38 → 40 taken 45 times.
231 overlay_darklighten_sse41<overlay_darken_sse_cmp, overlay_darken_c_cmp>(p1Y, p1U, p1V, p2Y, p2U, p2V, p1_pitch, p2_pitch, width, height);
339 4 }
340 4 void overlay_lighten_sse41(BYTE *p1Y, BYTE *p1U, BYTE *p1V, const BYTE *p2Y, const BYTE *p2U, const BYTE *p2V, int p1_pitch, int p2_pitch, int width, int height) {
341
2/2
✓ Branch 38 → 39 taken 68 times.
✓ Branch 38 → 40 taken 41 times.
231 overlay_darklighten_sse41<overlay_lighten_sse_cmp, overlay_lighten_c_cmp>(p1Y, p1U, p1V, p2Y, p2U, p2V, p1_pitch, p2_pitch, width, height);
342 4 }
343
344
345 // ---------------------------------------------------------------------------
346 // Family 1: weighted_merge — SSE2 (no mask, flat weight, >> 15 shift)
347 // weight + invweight == 32768; boundary values (0, 32768) are caller early-outs.
348 // All intrinsics here are SSE2-level; no GCC target attribute needed.
349 // ---------------------------------------------------------------------------
350
351 2 static void weighted_merge_uint8_sse2_impl(
352 BYTE* p1, const BYTE* p2, int p1_pitch, int p2_pitch,
353 int rowsize, int height, int weight_i, int invweight_i)
354 {
355 4 const __m128i mask = _mm_set1_epi32(invweight_i | (weight_i << 16));
356 2 const __m128i round_mask = _mm_set1_epi32(0x4000);
357 2 const __m128i zero = _mm_setzero_si128();
358
359 2 const int wMod16 = (rowsize / 16) * 16;
360
361
2/2
✓ Branch 67 → 13 taken 18 times.
✓ Branch 67 → 68 taken 2 times.
20 for (int y = 0; y < height; y++) {
362
2/2
✓ Branch 62 → 14 taken 31 times.
✓ Branch 62 → 63 taken 18 times.
49 for (int x = 0; x < wMod16; x += 16) {
363 31 __m128i px1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1 + x));
364 62 __m128i px2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2 + x));
365
366 31 __m128i p07 = _mm_unpacklo_epi8(px1, px2);
367 31 __m128i p815 = _mm_unpackhi_epi8(px1, px2);
368
369 31 __m128i p03 = _mm_unpacklo_epi8(p07, zero);
370 31 __m128i p47 = _mm_unpackhi_epi8(p07, zero);
371 31 __m128i p811 = _mm_unpacklo_epi8(p815, zero);
372 31 __m128i p1215 = _mm_unpackhi_epi8(p815, zero);
373
374 62 p03 = _mm_add_epi32(_mm_madd_epi16(p03, mask), round_mask);
375 62 p47 = _mm_add_epi32(_mm_madd_epi16(p47, mask), round_mask);
376 62 p811 = _mm_add_epi32(_mm_madd_epi16(p811, mask), round_mask);
377 62 p1215 = _mm_add_epi32(_mm_madd_epi16(p1215, mask), round_mask);
378
379 31 p03 = _mm_srli_epi32(p03, 15);
380 31 p47 = _mm_srli_epi32(p47, 15);
381 31 p811 = _mm_srli_epi32(p811, 15);
382 31 p1215 = _mm_srli_epi32(p1215, 15);
383
384 31 p07 = _mm_packs_epi32(p03, p47);
385 31 p815 = _mm_packs_epi32(p811, p1215);
386
387 31 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1 + x),
388 _mm_packus_epi16(p07, p815));
389 }
390
391 // Scalar tail
392
2/2
✓ Branch 65 → 64 taken 130 times.
✓ Branch 65 → 66 taken 18 times.
148 for (int x = wMod16; x < rowsize; ++x)
393 130 p1[x] = (uint8_t)((p1[x] * invweight_i + p2[x] * weight_i + 16384) >> 15);
394
395 18 p1 += p1_pitch;
396 18 p2 += p2_pitch;
397 }
398 2 }
399
400 // lessthan16bit=true: 10/12/14-bit — values fit positive int16, no pivot needed
401 // lessthan16bit=false: full 16-bit — signed pivot for unsigned-to-signed madd safety
402 template<bool lessthan16bit>
403 4 static void weighted_merge_uint16_sse2_impl(
404 BYTE* p1, const BYTE* p2, int p1_pitch, int p2_pitch,
405 int rowsize, int height, int weight_i, int invweight_i)
406 {
407 8 const __m128i mask = _mm_set1_epi32((weight_i << 16) + invweight_i);
408 4 const __m128i round_mask = _mm_set1_epi32(0x4000);
409 4 const __m128i signed_shift = _mm_set1_epi16(-32768);
410
411 4 const int wMod16 = (rowsize / 16) * 16;
412
413
4/4
void weighted_merge_uint16_sse2_impl<false>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 51 → 15 taken 13 times.
✓ Branch 51 → 52 taken 1 time.
void weighted_merge_uint16_sse2_impl<true>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 45 → 15 taken 27 times.
✓ Branch 45 → 46 taken 3 times.
44 for (int y = 0; y < height; y++) {
414
4/4
void weighted_merge_uint16_sse2_impl<false>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 46 → 16 taken 13 times.
✓ Branch 46 → 47 taken 13 times.
void weighted_merge_uint16_sse2_impl<true>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 40 → 16 taken 54 times.
✓ Branch 40 → 41 taken 27 times.
107 for (int x = 0; x < wMod16; x += 16) {
415 67 __m128i px1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1 + x));
416 134 __m128i px2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2 + x));
417
418 if constexpr (!lessthan16bit) {
419 13 px1 = _mm_add_epi16(px1, signed_shift);
420 13 px2 = _mm_add_epi16(px2, signed_shift);
421 }
422
423 67 __m128i p03 = _mm_unpacklo_epi16(px1, px2);
424 67 __m128i p47 = _mm_unpackhi_epi16(px1, px2);
425
426 134 p03 = _mm_add_epi32(_mm_madd_epi16(p03, mask), round_mask);
427 134 p47 = _mm_add_epi32(_mm_madd_epi16(p47, mask), round_mask);
428
429 67 p03 = _mm_srai_epi32(p03, 15);
430 67 p47 = _mm_srai_epi32(p47, 15);
431
432 67 __m128i p07 = _mm_packs_epi32(p03, p47);
433 if constexpr (!lessthan16bit) {
434 13 p07 = _mm_add_epi16(p07, signed_shift);
435 }
436
437 67 _mm_storeu_si128(reinterpret_cast<__m128i*>(p1 + x), p07);
438 }
439
440 // Scalar tail
441
4/4
void weighted_merge_uint16_sse2_impl<false>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 49 → 48 taken 91 times.
✓ Branch 49 → 50 taken 13 times.
void weighted_merge_uint16_sse2_impl<true>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 43 → 42 taken 91 times.
✓ Branch 43 → 44 taken 27 times.
222 for (int x = wMod16 / 2; x < rowsize / 2; ++x) {
442 182 reinterpret_cast<uint16_t*>(p1)[x] = (uint16_t)(
443 182 (reinterpret_cast<uint16_t*>(p1)[x] * invweight_i +
444 182 reinterpret_cast<const uint16_t*>(p2)[x] * weight_i + 16384) >> 15);
445 }
446
447 40 p1 += p1_pitch;
448 40 p2 += p2_pitch;
449 }
450 4 }
451
452 6 void weighted_merge_sse2(BYTE* p1, const BYTE* p2, int p1_pitch, int p2_pitch,
453 int width, int height, int weight, int invweight, int bits_per_pixel)
454 {
455
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 4 times.
6 const int pixelsize = bits_per_pixel <= 8 ? 1 : 2;
456 6 const int rowsize = width * pixelsize;
457
458
2/2
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 7 taken 4 times.
6 if (bits_per_pixel == 8)
459 2 weighted_merge_uint8_sse2_impl(p1, p2, p1_pitch, p2_pitch, rowsize, height, weight, invweight);
460
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 3 times.
4 else if (bits_per_pixel == 16)
461 1 weighted_merge_uint16_sse2_impl<false>(p1, p2, p1_pitch, p2_pitch, rowsize, height, weight, invweight);
462 else // 10, 12, 14-bit
463 3 weighted_merge_uint16_sse2_impl<true>(p1, p2, p1_pitch, p2_pitch, rowsize, height, weight, invweight);
464 6 }
465
466 4 void weighted_merge_float_sse2(BYTE* p1, const BYTE* p2, int p1_pitch, int p2_pitch,
467 int width, int height, float weight_f)
468 {
469 4 const float invweight_f = 1.0f - weight_f;
470 4 const auto v_weight = _mm_set1_ps(weight_f);
471 4 const auto v_invweight = _mm_set1_ps(invweight_f);
472 4 const int rowsize = width * 4;
473 4 const int wMod16 = (rowsize / 16) * 16;
474
475
2/2
✓ Branch 25 → 7 taken 19 times.
✓ Branch 25 → 26 taken 4 times.
23 for (int y = 0; y < height; y++) {
476
2/2
✓ Branch 20 → 8 taken 76 times.
✓ Branch 20 → 21 taken 19 times.
95 for (int x = 0; x < wMod16; x += 16) {
477 76 auto px1 = _mm_loadu_ps(reinterpret_cast<const float*>(p1 + x));
478 152 auto px2 = _mm_loadu_ps(reinterpret_cast<const float*>(p2 + x));
479 // p1 + (p2 - p1) * w == p1*(1-w) + p2*w
480 // choose the latter to match C ref
481 152 auto res = _mm_add_ps(_mm_mul_ps(px1, v_invweight), _mm_mul_ps(px2, v_weight));
482 // old linear interpolation: _mm_add_ps(px1, _mm_mul_ps(_mm_sub_ps(px2, px1), v_weight))
483 76 _mm_storeu_ps(reinterpret_cast<float*>(p1 + x), res);
484 }
485 // Scalar tail
486
2/2
✓ Branch 23 → 22 taken 19 times.
✓ Branch 23 → 24 taken 19 times.
38 for (int x = wMod16 / 4; x < width; ++x) {
487 19 reinterpret_cast<float*>(p1)[x] =
488 19 reinterpret_cast<float*>(p1)[x] * invweight_f +
489 19 reinterpret_cast<const float*>(p2)[x] * weight_f;
490 }
491 19 p1 += p1_pitch;
492 19 p2 += p2_pitch;
493 }
494 4 }
495
496 // ---------------------------------------------------------------------------
497 // Overlay blend masked getter — returns masked_merge_sse41_impl instantiation.
498 // is_chroma=false → always MASK444 (luma).
499 // is_chroma=true → placement-aware maskMode (chroma).
500 // No target("sse4.1") needed: getter only returns a function pointer, no intrinsics.
501 // ---------------------------------------------------------------------------
502 8138 masked_merge_fn_t* get_overlay_blend_masked_fn_sse41(bool is_chroma, MaskMode maskMode)
503 {
504 #define DISPATCH_OVERLAY_BLEND_SSE41(MaskType) \
505 return is_chroma ? masked_merge_sse41_impl<MaskType> \
506 : masked_merge_sse41_impl<MASK444>;
507
508
7/9
✓ Branch 2 → 3 taken 2158 times.
✓ Branch 2 → 4 taken 1443 times.
✓ Branch 2 → 8 taken 910 times.
✓ Branch 2 → 12 taken 728 times.
✓ Branch 2 → 16 taken 1443 times.
✓ Branch 2 → 20 taken 728 times.
✓ Branch 2 → 24 taken 728 times.
✗ Branch 2 → 28 not taken.
✗ Branch 2 → 32 not taken.
8138 switch (maskMode) {
509 2158 case MASK444: DISPATCH_OVERLAY_BLEND_SSE41(MASK444)
510
1/2
✓ Branch 4 → 5 taken 1443 times.
✗ Branch 4 → 6 not taken.
1443 case MASK420: DISPATCH_OVERLAY_BLEND_SSE41(MASK420)
511
1/2
✓ Branch 8 → 9 taken 910 times.
✗ Branch 8 → 10 not taken.
910 case MASK420_MPEG2: DISPATCH_OVERLAY_BLEND_SSE41(MASK420_MPEG2)
512
1/2
✓ Branch 12 → 13 taken 728 times.
✗ Branch 12 → 14 not taken.
728 case MASK420_TOPLEFT: DISPATCH_OVERLAY_BLEND_SSE41(MASK420_TOPLEFT)
513
1/2
✓ Branch 16 → 17 taken 1443 times.
✗ Branch 16 → 18 not taken.
1443 case MASK422: DISPATCH_OVERLAY_BLEND_SSE41(MASK422)
514
1/2
✓ Branch 20 → 21 taken 728 times.
✗ Branch 20 → 22 not taken.
728 case MASK422_MPEG2: DISPATCH_OVERLAY_BLEND_SSE41(MASK422_MPEG2)
515
1/2
✓ Branch 24 → 25 taken 728 times.
✗ Branch 24 → 26 not taken.
728 case MASK422_TOPLEFT: DISPATCH_OVERLAY_BLEND_SSE41(MASK422_TOPLEFT)
516 case MASK411: DISPATCH_OVERLAY_BLEND_SSE41(MASK411)
517 }
518 #undef DISPATCH_OVERLAY_BLEND_SSE41
519 return masked_merge_sse41_impl<MASK444>; // unreachable
520 }
521
522 // Layer SSE4.1 dispatcher has moved to filters/intel/layer_sse41.cpp
523
524 // ---------------------------------------------------------------------------
525 // Per-row chroma mask preparation for the scratch path in OF_blend.cpp.
526 // Dispatches on MaskMode at runtime; full_opacity known at compile time.
527 // Defined here so masked_rowprep_sse41.hpp is only included in this TU.
528 // ---------------------------------------------------------------------------
529 template<typename pixel_t, bool full_opacity>
530 #if defined(GCC) || defined(CLANG)
531 __attribute__((__target__("sse4.1")))
532 #endif
533 void do_fill_chroma_row_sse41(
534 std::vector<pixel_t>& buf, const pixel_t* luma_row,
535 int luma_pitch_pixels, int chroma_w, MaskMode mode,
536 int opacity_i, int half, MagicDiv magic)
537 {
538 switch (mode) {
539 case MASK411:
540 prepare_effective_mask_for_row_sse41<MASK411, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
541 case MASK420:
542 prepare_effective_mask_for_row_sse41<MASK420, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
543 case MASK420_MPEG2:
544 prepare_effective_mask_for_row_sse41<MASK420_MPEG2, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
545 case MASK420_TOPLEFT:
546 prepare_effective_mask_for_row_sse41<MASK420_TOPLEFT, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
547 case MASK422:
548 prepare_effective_mask_for_row_sse41<MASK422, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
549 case MASK422_MPEG2:
550 prepare_effective_mask_for_row_sse41<MASK422_MPEG2, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
551 case MASK422_TOPLEFT:
552 prepare_effective_mask_for_row_sse41<MASK422_TOPLEFT, pixel_t, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity_i, half, magic); break;
553 default: break;
554 }
555 }
556
557 // Explicit instantiation definitions for the four combinations used by OF_blend.cpp.
558 template void do_fill_chroma_row_sse41<uint8_t, true> (std::vector<uint8_t>&, const uint8_t*, int, int, MaskMode, int, int, MagicDiv);
559 template void do_fill_chroma_row_sse41<uint8_t, false>(std::vector<uint8_t>&, const uint8_t*, int, int, MaskMode, int, int, MagicDiv);
560 template void do_fill_chroma_row_sse41<uint16_t, true> (std::vector<uint16_t>&, const uint16_t*, int, int, MaskMode, int, int, MagicDiv);
561 template void do_fill_chroma_row_sse41<uint16_t, false>(std::vector<uint16_t>&, const uint16_t*, int, int, MaskMode, int, int, MagicDiv);
562
563 template<bool full_opacity>
564 void do_fill_chroma_row_float_sse41(
565 std::vector<float>& buf, const float* luma_row,
566 int luma_pitch_pixels, int chroma_w, MaskMode mode,
567 float opacity)
568 {
569 switch (mode) {
570 case MASK411:
571 prepare_effective_mask_for_row_float_sse41<MASK411, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
572 case MASK420:
573 prepare_effective_mask_for_row_float_sse41<MASK420, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
574 case MASK420_MPEG2:
575 prepare_effective_mask_for_row_float_sse41<MASK420_MPEG2, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
576 case MASK420_TOPLEFT:
577 prepare_effective_mask_for_row_float_sse41<MASK420_TOPLEFT, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
578 case MASK422:
579 prepare_effective_mask_for_row_float_sse41<MASK422, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
580 case MASK422_MPEG2:
581 prepare_effective_mask_for_row_float_sse41<MASK422_MPEG2, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
582 case MASK422_TOPLEFT:
583 prepare_effective_mask_for_row_float_sse41<MASK422_TOPLEFT, full_opacity>(luma_row, luma_pitch_pixels, chroma_w, buf, opacity); break;
584 default: break;
585 }
586 }
587
588
589 template void do_fill_chroma_row_float_sse41<true>(std::vector<float>&, const float*, int, int, MaskMode, float);
590 template void do_fill_chroma_row_float_sse41<false>(std::vector<float>&, const float*, int, int, MaskMode, float);
591
592 // and for float:
593 6136 masked_merge_float_fn_t* get_overlay_blend_masked_float_fn_sse41(bool is_chroma, MaskMode maskMode)
594 {
595 #define DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MaskType) \
596 return is_chroma ? masked_merge_float_sse41_impl<MaskType> \
597 : masked_merge_float_sse41_impl<MASK444>;
598
599
7/9
✓ Branch 2 → 3 taken 1014 times.
✓ Branch 2 → 4 taken 1014 times.
✓ Branch 2 → 8 taken 910 times.
✓ Branch 2 → 12 taken 728 times.
✓ Branch 2 → 16 taken 1014 times.
✓ Branch 2 → 20 taken 728 times.
✓ Branch 2 → 24 taken 728 times.
✗ Branch 2 → 28 not taken.
✗ Branch 2 → 32 not taken.
6136 switch (maskMode) {
600 1014 case MASK444: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK444)
601
1/2
✓ Branch 4 → 5 taken 1014 times.
✗ Branch 4 → 6 not taken.
1014 case MASK420: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK420)
602
1/2
✓ Branch 8 → 9 taken 910 times.
✗ Branch 8 → 10 not taken.
910 case MASK420_MPEG2: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK420_MPEG2)
603
1/2
✓ Branch 12 → 13 taken 728 times.
✗ Branch 12 → 14 not taken.
728 case MASK420_TOPLEFT: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK420_TOPLEFT)
604
1/2
✓ Branch 16 → 17 taken 1014 times.
✗ Branch 16 → 18 not taken.
1014 case MASK422: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK422)
605
1/2
✓ Branch 20 → 21 taken 728 times.
✗ Branch 20 → 22 not taken.
728 case MASK422_MPEG2: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK422_MPEG2)
606
1/2
✓ Branch 24 → 25 taken 728 times.
✗ Branch 24 → 26 not taken.
728 case MASK422_TOPLEFT: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK422_TOPLEFT)
607 case MASK411: DISPATCH_OVERLAY_BLEND_FLOAT_SSE41(MASK411)
608 }
609 #undef DISPATCH_OVERLAY_BLEND_FLOAT_SSE41
610 return masked_merge_float_sse41_impl<MASK444>; // unreachable
611 }
612
613
614