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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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/4void 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 |