filters/intel/layer_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 | |||
| 36 | |||
| 37 | // Avisynth filter: Layer | ||
| 38 | // by "poptones" (poptones@myrealbox.com) | ||
| 39 | |||
| 40 | #include "layer_sse.h" | ||
| 41 | #include "../layer.h" | ||
| 42 | |||
| 43 | #ifdef AVS_WINDOWS | ||
| 44 | #include <avs/win.h> | ||
| 45 | #else | ||
| 46 | #include <avs/posix.h> | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #include <avs/minmax.h> | ||
| 50 | #include <avs/alignment.h> | ||
| 51 | #include "../core/internal.h" | ||
| 52 | |||
| 53 | // Intrinsics base header + really required extension headers | ||
| 54 | #if defined(_MSC_VER) | ||
| 55 | #include <intrin.h> // MSVC | ||
| 56 | #else | ||
| 57 | #include <x86intrin.h> // GCC/MinGW/Clang/LLVM | ||
| 58 | #endif | ||
| 59 | |||
| 60 | #include "../convert/convert_planar.h" | ||
| 61 | #include <algorithm> | ||
| 62 | |||
| 63 | |||
| 64 | static AVS_FORCEINLINE __m128i mask_core_sse2(__m128i& src, __m128i& alpha, __m128i& not_alpha_mask, __m128i& zero, __m128i& matrix, __m128i& round_mask) { | ||
| 65 | 18 | __m128i not_alpha = _mm_and_si128(src, not_alpha_mask); | |
| 66 | |||
| 67 | 9 | __m128i pixel0 = _mm_unpacklo_epi8(alpha, zero); | |
| 68 | 9 | __m128i pixel1 = _mm_unpackhi_epi8(alpha, zero); | |
| 69 | |||
| 70 | 9 | pixel0 = _mm_madd_epi16(pixel0, matrix); | |
| 71 | 18 | pixel1 = _mm_madd_epi16(pixel1, matrix); | |
| 72 | |||
| 73 | 27 | __m128i tmp = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(pixel0), _mm_castsi128_ps(pixel1), _MM_SHUFFLE(3, 1, 3, 1))); | |
| 74 | 27 | __m128i tmp2 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(pixel0), _mm_castsi128_ps(pixel1), _MM_SHUFFLE(2, 0, 2, 0))); | |
| 75 | |||
| 76 | 9 | tmp = _mm_add_epi32(tmp, tmp2); | |
| 77 | 18 | tmp = _mm_add_epi32(tmp, round_mask); | |
| 78 | 9 | tmp = _mm_srli_epi32(tmp, 15); | |
| 79 | 9 | __m128i result_alpha = _mm_slli_epi32(tmp, 24); | |
| 80 | |||
| 81 | 9 | return _mm_or_si128(result_alpha, not_alpha); | |
| 82 | } | ||
| 83 | |||
| 84 | 1 | void mask_sse2(BYTE* srcp, const BYTE* alphap, int src_pitch, int alpha_pitch, size_t width, size_t height) { | |
| 85 | 1 | __m128i matrix = _mm_set_epi16(0, cyr, cyg, cyb, 0, cyr, cyg, cyb); | |
| 86 | 1 | __m128i zero = _mm_setzero_si128(); | |
| 87 | 1 | __m128i round_mask = _mm_set1_epi32(16384); | |
| 88 | 1 | __m128i not_alpha_mask = _mm_set1_epi32(0x00FFFFFF); | |
| 89 | |||
| 90 | 1 | size_t width_bytes = width * 4; | |
| 91 | 1 | size_t width_mod16 = width_bytes / 16 * 16; | |
| 92 | |||
| 93 |
2/2✓ Branch 99 → 15 taken 3 times.
✓ Branch 99 → 100 taken 1 time.
|
4 | for (size_t y = 0; y < height; ++y) { |
| 94 |
2/2✓ Branch 56 → 16 taken 6 times.
✓ Branch 56 → 57 taken 3 times.
|
9 | for (size_t x = 0; x < width_mod16; x += 16) { |
| 95 | 6 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x)); | |
| 96 | 12 | __m128i alpha = _mm_load_si128(reinterpret_cast<const __m128i*>(alphap + x)); | |
| 97 | 6 | __m128i result = mask_core_sse2(src, alpha, not_alpha_mask, zero, matrix, round_mask); | |
| 98 | |||
| 99 | 6 | _mm_store_si128(reinterpret_cast<__m128i*>(srcp + x), result); | |
| 100 | } | ||
| 101 | |||
| 102 |
1/2✓ Branch 57 → 58 taken 3 times.
✗ Branch 57 → 98 not taken.
|
3 | if (width_mod16 < width_bytes) { |
| 103 | 3 | __m128i src = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + width_bytes - 16)); | |
| 104 | 6 | __m128i alpha = _mm_loadu_si128(reinterpret_cast<const __m128i*>(alphap + width_bytes - 16)); | |
| 105 | 3 | __m128i result = mask_core_sse2(src, alpha, not_alpha_mask, zero, matrix, round_mask); | |
| 106 | |||
| 107 | 3 | _mm_storeu_si128(reinterpret_cast<__m128i*>(srcp + width_bytes - 16), result); | |
| 108 | } | ||
| 109 | |||
| 110 | 3 | srcp += src_pitch; | |
| 111 | 3 | alphap += alpha_pitch; | |
| 112 | } | ||
| 113 | 1 | } | |
| 114 | |||
| 115 | 1 | void colorkeymask_sse2(BYTE* pf, int pitch, int color, int height, int width, int tolB, int tolG, int tolR) { | |
| 116 | 1 | unsigned int t = 0xFF000000 | (tolR << 16) | (tolG << 8) | tolB; | |
| 117 | 2 | __m128i tolerance = _mm_set1_epi32(t); | |
| 118 | 1 | __m128i colorv = _mm_set1_epi32(color); | |
| 119 | 1 | __m128i zero = _mm_setzero_si128(); | |
| 120 | |||
| 121 | 1 | BYTE* endp = pf + pitch * height; | |
| 122 | |||
| 123 |
2/2✓ Branch 31 → 13 taken 12 times.
✓ Branch 31 → 32 taken 1 time.
|
13 | while (pf < endp) |
| 124 | { | ||
| 125 | 12 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(pf)); | |
| 126 | 12 | __m128i gt = _mm_subs_epu8(colorv, src); | |
| 127 | 12 | __m128i lt = _mm_subs_epu8(src, colorv); | |
| 128 | 12 | __m128i absdiff = _mm_or_si128(gt, lt); //abs(color - src) | |
| 129 | |||
| 130 | 12 | __m128i not_passed = _mm_subs_epu8(absdiff, tolerance); | |
| 131 | 12 | __m128i passed = _mm_cmpeq_epi32(not_passed, zero); | |
| 132 | 12 | passed = _mm_slli_epi32(passed, 24); | |
| 133 | 12 | __m128i result = _mm_andnot_si128(passed, src); | |
| 134 | |||
| 135 | _mm_store_si128(reinterpret_cast<__m128i*>(pf), result); | ||
| 136 | |||
| 137 | 12 | pf += 16; | |
| 138 | } | ||
| 139 | 1 | } | |
| 140 | |||
| 141 | |||
| 142 | 2 | void invert_frame_inplace_sse2(BYTE* frame, int pitch, int width, int height, int mask) { | |
| 143 | 2 | __m128i maskv = _mm_set1_epi32(mask); | |
| 144 | |||
| 145 | 2 | BYTE* endp = frame + pitch * height; | |
| 146 | |||
| 147 |
2/2✓ Branch 13 → 7 taken 58 times.
✓ Branch 13 → 14 taken 2 times.
|
60 | while (frame < endp) { |
| 148 | 58 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(frame)); | |
| 149 | 58 | __m128i inv = _mm_xor_si128(src, maskv); | |
| 150 | _mm_store_si128(reinterpret_cast<__m128i*>(frame), inv); | ||
| 151 | 58 | frame += 16; | |
| 152 | } | ||
| 153 | 2 | } | |
| 154 | |||
| 155 | 2 | void invert_frame_uint16_inplace_sse2(BYTE* frame, int pitch, int width, int height, uint64_t mask64) { | |
| 156 | 2 | __m128i maskv = _mm_set_epi32((uint32_t)(mask64 >> 32), (uint32_t)mask64, (uint32_t)(mask64 >> 32), (uint32_t)mask64); | |
| 157 | |||
| 158 | 2 | BYTE* endp = frame + pitch * height; | |
| 159 | |||
| 160 |
2/2✓ Branch 11 → 5 taken 58 times.
✓ Branch 11 → 12 taken 2 times.
|
60 | while (frame < endp) { |
| 161 | 58 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(frame)); | |
| 162 | 58 | __m128i inv = _mm_xor_si128(src, maskv); | |
| 163 | _mm_store_si128(reinterpret_cast<__m128i*>(frame), inv); | ||
| 164 | 58 | frame += 16; | |
| 165 | } | ||
| 166 | 2 | } | |
| 167 | |||
| 168 | template<bool chroma> | ||
| 169 | 2 | void invert_plane_sse2_u8(uint8_t* dstp, const uint8_t* srcp, int src_pitch, int dst_pitch, int width, int height, int /*bits_per_pixel*/) | |
| 170 | { | ||
| 171 | 2 | const __m128i v_ff = _mm_set1_epi8((char)0xFF); | |
| 172 | 2 | const __m128i v_one = _mm_set1_epi8(1); | |
| 173 |
4/4void invert_plane_sse2_u8<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 20 → 11 taken 3 times.
✓ Branch 20 → 21 taken 1 time.
void invert_plane_sse2_u8<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 22 → 11 taken 3 times.
✓ Branch 22 → 23 taken 1 time.
|
8 | for (int y = 0; y < height; ++y) { |
| 174 | |||
| 175 |
4/4void invert_plane_sse2_u8<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 18 → 12 taken 12 times.
✓ Branch 18 → 19 taken 3 times.
void invert_plane_sse2_u8<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 20 → 12 taken 12 times.
✓ Branch 20 → 21 taken 3 times.
|
30 | for (int x = 0; x < width; x += 16) { |
| 176 | 48 | __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x)); | |
| 177 | __m128i r; | ||
| 178 | if constexpr (chroma) | ||
| 179 | 12 | r = _mm_xor_si128(_mm_subs_epu8(s, v_one), v_ff); | |
| 180 | else | ||
| 181 | 12 | r = _mm_xor_si128(s, v_ff); | |
| 182 | 24 | _mm_store_si128(reinterpret_cast<__m128i*>(dstp + x), r); | |
| 183 | } | ||
| 184 | 6 | srcp += src_pitch; | |
| 185 | 6 | dstp += dst_pitch; | |
| 186 | } | ||
| 187 | 2 | } | |
| 188 | |||
| 189 | template<bool chroma> | ||
| 190 | 10 | void invert_plane_sse2_u16(uint8_t* dstp, const uint8_t* srcp, int src_pitch, int dst_pitch, int width, int height, int bits_per_pixel) | |
| 191 | { | ||
| 192 | 10 | const int max_pixel_value = (1 << bits_per_pixel) - 1; | |
| 193 | 20 | const __m128i v_max = _mm_set1_epi16((short)max_pixel_value); | |
| 194 | 10 | const __m128i v_one = _mm_set1_epi16(1); | |
| 195 |
4/4void invert_plane_sse2_u16<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 20 → 11 taken 17 times.
✓ Branch 20 → 21 taken 5 times.
void invert_plane_sse2_u16<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 22 → 11 taken 17 times.
✓ Branch 22 → 23 taken 5 times.
|
44 | for (int y = 0; y < height; ++y) { |
| 196 | 34 | const uint16_t* s16 = reinterpret_cast<const uint16_t*>(srcp); | |
| 197 | 34 | uint16_t* d16 = reinterpret_cast<uint16_t*>(dstp); | |
| 198 |
4/4void invert_plane_sse2_u16<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 18 → 12 taken 68 times.
✓ Branch 18 → 19 taken 17 times.
void invert_plane_sse2_u16<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 20 → 12 taken 68 times.
✓ Branch 20 → 21 taken 17 times.
|
170 | for (int x = 0; x < width; x += 8) { |
| 199 | 272 | __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(s16 + x)); | |
| 200 | __m128i r; | ||
| 201 | if constexpr (chroma) | ||
| 202 | 68 | r = _mm_xor_si128(_mm_subs_epu16(s, v_one), v_max); | |
| 203 | else | ||
| 204 | 68 | r = _mm_xor_si128(s, v_max); | |
| 205 | 136 | _mm_store_si128(reinterpret_cast<__m128i*>(d16 + x), r); | |
| 206 | } | ||
| 207 | 34 | srcp += src_pitch; | |
| 208 | 34 | dstp += dst_pitch; | |
| 209 | } | ||
| 210 | 10 | } | |
| 211 | |||
| 212 | template<bool chroma> | ||
| 213 | 4 | void invert_plane_sse2_f32(uint8_t* dstp, const uint8_t* srcp, int src_pitch, int dst_pitch, int width, int height, int /*bits_per_pixel*/) | |
| 214 | { | ||
| 215 | 4 | const __m128 v_one = _mm_set1_ps(1.0f); | |
| 216 | 4 | const __m128 v_sign = _mm_set1_ps(-0.0f); | |
| 217 |
4/4void invert_plane_sse2_f32<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 16 → 7 taken 8 times.
✓ Branch 16 → 17 taken 2 times.
void invert_plane_sse2_f32<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 16 → 7 taken 8 times.
✓ Branch 16 → 17 taken 2 times.
|
20 | for (int y = 0; y < height; ++y) { |
| 218 | 16 | const float* sf = reinterpret_cast<const float*>(srcp); | |
| 219 | 16 | float* df = reinterpret_cast<float*>(dstp); | |
| 220 |
4/4void invert_plane_sse2_f32<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 14 → 8 taken 32 times.
✓ Branch 14 → 15 taken 8 times.
void invert_plane_sse2_f32<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 14 → 8 taken 32 times.
✓ Branch 14 → 15 taken 8 times.
|
80 | for (int x = 0; x < width; x += 4) { |
| 221 | 128 | __m128 s = _mm_load_ps(sf + x); | |
| 222 | 64 | __m128 r = chroma ? _mm_xor_ps(s, v_sign) : _mm_sub_ps(v_one, s); | |
| 223 | 64 | _mm_store_ps(df + x, r); | |
| 224 | } | ||
| 225 | 16 | srcp += src_pitch; dstp += dst_pitch; | |
| 226 | } | ||
| 227 | 4 | } | |
| 228 | |||
| 229 | template void invert_plane_sse2_u8<false>(uint8_t*, const uint8_t*, int, int, int, int, int); | ||
| 230 | template void invert_plane_sse2_u8<true>(uint8_t*, const uint8_t*, int, int, int, int, int); | ||
| 231 | template void invert_plane_sse2_u16<false>(uint8_t*, const uint8_t*, int, int, int, int, int); | ||
| 232 | template void invert_plane_sse2_u16<true>(uint8_t*, const uint8_t*, int, int, int, int, int); | ||
| 233 | template void invert_plane_sse2_f32<false>(uint8_t*, const uint8_t*, int, int, int, int, int); | ||
| 234 | template void invert_plane_sse2_f32<true>(uint8_t*, const uint8_t*, int, int, int, int, int); | ||
| 235 | |||
| 236 | /******************************* | ||
| 237 | ******* Layer Filter ****** | ||
| 238 | *******************************/ | ||
| 239 | |||
| 240 | 1 | void layer_rgb32_fast_sse2(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level) { | |
| 241 | AVS_UNUSED(level); | ||
| 242 | 1 | int width_bytes = width * 4; | |
| 243 | 1 | int width_mod16 = width_bytes / 16 * 16; | |
| 244 | |||
| 245 |
2/2✓ Branch 17 → 3 taken 3 times.
✓ Branch 17 → 18 taken 1 time.
|
4 | for (int y = 0; y < height; ++y) { |
| 246 |
2/2✓ Branch 12 → 4 taken 6 times.
✓ Branch 12 → 13 taken 3 times.
|
9 | for (int x = 0; x < width_mod16; x += 16) { |
| 247 | 6 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(dstp + x)); | |
| 248 | 12 | __m128i ovr = _mm_load_si128(reinterpret_cast<const __m128i*>(ovrp + x)); | |
| 249 | |||
| 250 | 6 | _mm_store_si128(reinterpret_cast<__m128i*>(dstp + x), _mm_avg_epu8(src, ovr)); | |
| 251 | } | ||
| 252 | |||
| 253 |
2/2✓ Branch 15 → 14 taken 36 times.
✓ Branch 15 → 16 taken 3 times.
|
39 | for (int x = width_mod16; x < width_bytes; ++x) { |
| 254 | 36 | dstp[x] = (dstp[x] + ovrp[x] + 1) / 2; | |
| 255 | } | ||
| 256 | |||
| 257 | 3 | dstp += dst_pitch; | |
| 258 | 3 | ovrp += overlay_pitch; | |
| 259 | } | ||
| 260 | 1 | } | |
| 261 | |||
| 262 | |||
| 263 | template<typename pixel_t> | ||
| 264 | 4 | void layer_genericplane_fast_sse2(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level) { | |
| 265 | AVS_UNUSED(level); | ||
| 266 | 4 | int width_bytes = width * sizeof(pixel_t); | |
| 267 | 4 | int width_mod16 = width_bytes / 16 * 16; | |
| 268 | |||
| 269 |
4/4void layer_genericplane_fast_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 17 → 3 taken 10 times.
✓ Branch 17 → 18 taken 2 times.
void layer_genericplane_fast_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 17 → 3 taken 10 times.
✓ Branch 17 → 18 taken 2 times.
|
24 | for (int y = 0; y < height; ++y) { |
| 270 |
4/4void layer_genericplane_fast_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 12 → 4 taken 20 times.
✓ Branch 12 → 13 taken 10 times.
void layer_genericplane_fast_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 12 → 4 taken 20 times.
✓ Branch 12 → 13 taken 10 times.
|
60 | for (int x = 0; x < width_mod16; x += 16) { |
| 271 | 40 | __m128i src = _mm_loadu_si128(reinterpret_cast<const __m128i*>(dstp + x)); | |
| 272 | 80 | __m128i ovr = _mm_loadu_si128(reinterpret_cast<const __m128i*>(ovrp + x)); | |
| 273 | if constexpr (sizeof(pixel_t) == 1) | ||
| 274 | 20 | _mm_storeu_si128(reinterpret_cast<__m128i*>(dstp + x), _mm_avg_epu8(src, ovr)); | |
| 275 | else | ||
| 276 | 20 | _mm_storeu_si128(reinterpret_cast<__m128i*>(dstp + x), _mm_avg_epu16(src, ovr)); | |
| 277 | } | ||
| 278 | |||
| 279 |
4/4void layer_genericplane_fast_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 15 → 14 taken 114 times.
✓ Branch 15 → 16 taken 10 times.
void layer_genericplane_fast_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 15 → 14 taken 52 times.
✓ Branch 15 → 16 taken 10 times.
|
186 | for (int x = width_mod16 / sizeof(pixel_t); x < width; ++x) { |
| 280 | 166 | reinterpret_cast<pixel_t*>(dstp)[x] = (reinterpret_cast<pixel_t*>(dstp)[x] + reinterpret_cast<const pixel_t*>(ovrp)[x] + 1) / 2; | |
| 281 | } | ||
| 282 | |||
| 283 | 20 | dstp += dst_pitch; | |
| 284 | 20 | ovrp += overlay_pitch; | |
| 285 | } | ||
| 286 | 4 | } | |
| 287 | |||
| 288 | // instantiate | ||
| 289 | template void layer_genericplane_fast_sse2<uint8_t>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 290 | template void layer_genericplane_fast_sse2<uint16_t>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 291 | |||
| 292 | /* RGB32 */ | ||
| 293 | |||
| 294 | //src format: xx xx xx xx | xx xx xx xx | a1 xx xx xx | a0 xx xx xx | ||
| 295 | //level_vector and one should be vectors of 32bit packed integers | ||
| 296 | static AVS_FORCEINLINE __m128i calculate_monochrome_alpha_sse2(const __m128i& src, const __m128i& level_vector, const __m128i& one) { | ||
| 297 | 576 | __m128i alpha = _mm_srli_epi32(src, 24); | |
| 298 | 288 | alpha = _mm_mullo_epi16(alpha, level_vector); | |
| 299 | 576 | alpha = _mm_add_epi32(alpha, one); | |
| 300 | 288 | alpha = _mm_srli_epi32(alpha, 8); | |
| 301 | 288 | alpha = _mm_shufflelo_epi16(alpha, _MM_SHUFFLE(2, 2, 0, 0)); | |
| 302 | 288 | return _mm_shuffle_epi32(alpha, _MM_SHUFFLE(1, 1, 0, 0)); | |
| 303 | } | ||
| 304 | |||
| 305 | static AVS_FORCEINLINE __m128i calculate_luma_sse2(const __m128i& src, const __m128i& rgb_coeffs, const __m128i& zero) { | ||
| 306 | AVS_UNUSED(zero); | ||
| 307 | 96 | __m128i temp = _mm_madd_epi16(src, rgb_coeffs); | |
| 308 | 336 | __m128i low = _mm_shuffle_epi32(temp, _MM_SHUFFLE(3, 3, 1, 1)); | |
| 309 | 336 | temp = _mm_add_epi32(low, temp); | |
| 310 | 336 | temp = _mm_srli_epi32(temp, 15); | |
| 311 | 336 | __m128i result = _mm_shufflelo_epi16(temp, _MM_SHUFFLE(0, 0, 0, 0)); | |
| 312 | 336 | return _mm_shufflehi_epi16(result, _MM_SHUFFLE(0, 0, 0, 0)); | |
| 313 | } | ||
| 314 | |||
| 315 | // must be unaligned load/store | ||
| 316 | template<bool use_chroma> | ||
| 317 | 6 | void layer_rgb32_mul_sse2(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level) { | |
| 318 | 6 | int mod2_width = width / 2 * 2; | |
| 319 | |||
| 320 | 6 | __m128i zero = _mm_setzero_si128(); | |
| 321 | 6 | __m128i level_vector = _mm_set1_epi32(level); | |
| 322 | 6 | __m128i one = _mm_set1_epi32(1); | |
| 323 | 6 | __m128i rgb_coeffs = _mm_set_epi16(0, cyr, cyg, cyb, 0, cyr, cyg, cyb); | |
| 324 | |||
| 325 |
4/4void layer_rgb32_mul_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 72 → 15 taken 11 times.
✓ Branch 72 → 73 taken 3 times.
void layer_rgb32_mul_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 65 → 15 taken 11 times.
✓ Branch 65 → 66 taken 3 times.
|
28 | for (int y = 0; y < height; ++y) { |
| 326 |
4/4void layer_rgb32_mul_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 67 → 16 taken 48 times.
✓ Branch 67 → 68 taken 11 times.
void layer_rgb32_mul_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 60 → 16 taken 48 times.
✓ Branch 60 → 61 taken 11 times.
|
118 | for (int x = 0; x < mod2_width; x += 2) { |
| 327 | 96 | __m128i src = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(dstp + x * 4)); | |
| 328 | 192 | __m128i ovr = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(ovrp + x * 4)); | |
| 329 | |||
| 330 | 96 | __m128i alpha = calculate_monochrome_alpha_sse2(ovr, level_vector, one); | |
| 331 | |||
| 332 | 96 | src = _mm_unpacklo_epi8(src, zero); | |
| 333 | 192 | ovr = _mm_unpacklo_epi8(ovr, zero); | |
| 334 | |||
| 335 | __m128i luma; | ||
| 336 | if (use_chroma) { | ||
| 337 | 48 | luma = ovr; | |
| 338 | } | ||
| 339 | else { | ||
| 340 | 48 | luma = calculate_luma_sse2(ovr, rgb_coeffs, zero); | |
| 341 | } | ||
| 342 | |||
| 343 | 96 | __m128i dst = _mm_mullo_epi16(luma, src); | |
| 344 | 96 | dst = _mm_srli_epi16(dst, 8); | |
| 345 | 96 | dst = _mm_subs_epi16(dst, src); | |
| 346 | 96 | dst = _mm_mullo_epi16(dst, alpha); | |
| 347 | 96 | dst = _mm_srli_epi16(dst, 8); | |
| 348 | 96 | dst = _mm_add_epi8(src, dst); | |
| 349 | |||
| 350 | 96 | dst = _mm_packus_epi16(dst, zero); | |
| 351 | |||
| 352 | 96 | _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + x * 4), dst); | |
| 353 | } | ||
| 354 | |||
| 355 |
2/4void layer_rgb32_mul_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 68 → 69 taken 11 times.
✗ Branch 68 → 71 not taken.
void layer_rgb32_mul_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 61 → 62 taken 11 times.
✗ Branch 61 → 64 not taken.
|
22 | if (width != mod2_width) { |
| 356 | 22 | int x = mod2_width; | |
| 357 | 22 | int alpha = (ovrp[x * 4 + 3] * level + 1) >> 8; | |
| 358 | |||
| 359 | if (use_chroma) { | ||
| 360 | 11 | dstp[x * 4] = dstp[x * 4] + (((((ovrp[x * 4] * dstp[x * 4]) >> 8) - dstp[x * 4]) * alpha) >> 8); | |
| 361 | 11 | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((((ovrp[x * 4 + 1] * dstp[x * 4 + 1]) >> 8) - dstp[x * 4 + 1]) * alpha) >> 8); | |
| 362 | 11 | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((((ovrp[x * 4 + 2] * dstp[x * 4 + 2]) >> 8) - dstp[x * 4 + 2]) * alpha) >> 8); | |
| 363 | 11 | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((((ovrp[x * 4 + 3] * dstp[x * 4 + 3]) >> 8) - dstp[x * 4 + 3]) * alpha) >> 8); | |
| 364 | } | ||
| 365 | else { | ||
| 366 | 11 | int luma = (cyb * ovrp[x * 4] + cyg * ovrp[x * 4 + 1] + cyr * ovrp[x * 4 + 2]) >> 15; | |
| 367 | |||
| 368 | 11 | dstp[x * 4] = dstp[x * 4] + (((((luma * dstp[x * 4]) >> 8) - dstp[x * 4]) * alpha) >> 8); | |
| 369 | 11 | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((((luma * dstp[x * 4 + 1]) >> 8) - dstp[x * 4 + 1]) * alpha) >> 8); | |
| 370 | 11 | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((((luma * dstp[x * 4 + 2]) >> 8) - dstp[x * 4 + 2]) * alpha) >> 8); | |
| 371 | 11 | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((((luma * dstp[x * 4 + 3]) >> 8) - dstp[x * 4 + 3]) * alpha) >> 8); | |
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | 22 | dstp += dst_pitch; | |
| 376 | 22 | ovrp += overlay_pitch; | |
| 377 | } | ||
| 378 | 6 | } | |
| 379 | |||
| 380 | // instantiate | ||
| 381 | template void layer_rgb32_mul_sse2<false>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 382 | template void layer_rgb32_mul_sse2<true>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 383 | |||
| 384 | |||
| 385 | // must be unaligned load/store | ||
| 386 | template<bool use_chroma> | ||
| 387 | 3 | void layer_rgb32_add_sse2(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level) { | |
| 388 | 3 | int mod2_width = width / 2 * 2; | |
| 389 | |||
| 390 | 3 | __m128i zero = _mm_setzero_si128(); | |
| 391 | 3 | __m128i level_vector = _mm_set1_epi32(level); | |
| 392 | 3 | __m128i one = _mm_set1_epi32(1); | |
| 393 | 3 | __m128i rgb_coeffs = _mm_set_epi16(0, cyr, cyg, cyb, 0, cyr, cyg, cyb); | |
| 394 | |||
| 395 | 3 | constexpr int rounder = 128; | |
| 396 | 3 | const __m128i rounder_simd = _mm_set1_epi16(rounder); | |
| 397 | |||
| 398 |
2/4void layer_rgb32_add_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 74 → 19 taken 11 times.
✓ Branch 74 → 75 taken 3 times.
void layer_rgb32_add_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✗ Branch 67 → 19 not taken.
✗ Branch 67 → 68 not taken.
|
14 | for (int y = 0; y < height; ++y) { |
| 399 |
2/4void layer_rgb32_add_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 69 → 20 taken 48 times.
✓ Branch 69 → 70 taken 11 times.
void layer_rgb32_add_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✗ Branch 62 → 20 not taken.
✗ Branch 62 → 63 not taken.
|
59 | for (int x = 0; x < mod2_width; x += 2) { |
| 400 | 48 | __m128i src = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(dstp + x * 4)); | |
| 401 | 96 | __m128i ovr = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(ovrp + x * 4)); | |
| 402 | |||
| 403 | 48 | __m128i alpha = calculate_monochrome_alpha_sse2(ovr, level_vector, one); | |
| 404 | |||
| 405 | 48 | src = _mm_unpacklo_epi8(src, zero); | |
| 406 | 96 | ovr = _mm_unpacklo_epi8(ovr, zero); | |
| 407 | |||
| 408 | __m128i luma; | ||
| 409 | if (use_chroma) { | ||
| 410 | ✗ | luma = ovr; | |
| 411 | } | ||
| 412 | else { | ||
| 413 | 48 | luma = calculate_luma_sse2(ovr, rgb_coeffs, zero); | |
| 414 | } | ||
| 415 | |||
| 416 | 48 | __m128i dst = _mm_subs_epi16(luma, src); | |
| 417 | 48 | dst = _mm_mullo_epi16(dst, alpha); | |
| 418 | 48 | dst = _mm_add_epi16(dst, rounder_simd); | |
| 419 | 48 | dst = _mm_srli_epi16(dst, 8); | |
| 420 | 48 | dst = _mm_add_epi8(src, dst); | |
| 421 | |||
| 422 | 48 | dst = _mm_packus_epi16(dst, zero); | |
| 423 | |||
| 424 | 48 | _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + x * 4), dst); | |
| 425 | } | ||
| 426 | |||
| 427 |
1/4void layer_rgb32_add_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 70 → 71 taken 11 times.
✗ Branch 70 → 73 not taken.
void layer_rgb32_add_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✗ Branch 63 → 64 not taken.
✗ Branch 63 → 66 not taken.
|
11 | if (width != mod2_width) { |
| 428 | 11 | int x = mod2_width; | |
| 429 | 11 | int alpha = (ovrp[x * 4 + 3] * level + 1) >> 8; | |
| 430 | |||
| 431 | if (use_chroma) { | ||
| 432 | ✗ | dstp[x * 4] = dstp[x * 4] + (((ovrp[x * 4] - dstp[x * 4]) * alpha + rounder) >> 8); | |
| 433 | ✗ | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((ovrp[x * 4 + 1] - dstp[x * 4 + 1]) * alpha + rounder) >> 8); | |
| 434 | ✗ | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((ovrp[x * 4 + 2] - dstp[x * 4 + 2]) * alpha + rounder) >> 8); | |
| 435 | ✗ | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((ovrp[x * 4 + 3] - dstp[x * 4 + 3]) * alpha + rounder) >> 8); | |
| 436 | } | ||
| 437 | else { | ||
| 438 | 11 | int luma = (cyb * ovrp[x * 4] + cyg * ovrp[x * 4 + 1] + cyr * ovrp[x * 4 + 2]) >> 15; | |
| 439 | |||
| 440 | 11 | dstp[x * 4] = dstp[x * 4] + (((luma - dstp[x * 4]) * alpha + rounder) >> 8); | |
| 441 | 11 | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((luma - dstp[x * 4 + 1]) * alpha + rounder) >> 8); | |
| 442 | 11 | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((luma - dstp[x * 4 + 2]) * alpha + rounder) >> 8); | |
| 443 | 11 | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((luma - dstp[x * 4 + 3]) * alpha + rounder) >> 8); | |
| 444 | } | ||
| 445 | } | ||
| 446 | |||
| 447 | 11 | dstp += dst_pitch; | |
| 448 | 11 | ovrp += overlay_pitch; | |
| 449 | } | ||
| 450 | 3 | } | |
| 451 | |||
| 452 | // instantiate | ||
| 453 | template void layer_rgb32_add_sse2<false>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 454 | template void layer_rgb32_add_sse2<true>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 455 | |||
| 456 | |||
| 457 | |||
| 458 | template<bool use_chroma> | ||
| 459 | 3 | void layer_rgb32_subtract_sse2(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level) { | |
| 460 | 3 | int mod2_width = width / 2 * 2; | |
| 461 | |||
| 462 | 3 | __m128i zero = _mm_setzero_si128(); | |
| 463 | 3 | __m128i level_vector = _mm_set1_epi32(level); | |
| 464 | 3 | __m128i one = _mm_set1_epi32(1); | |
| 465 | 3 | __m128i rgb_coeffs = _mm_set_epi16(0, cyr, cyg, cyb, 0, cyr, cyg, cyb); | |
| 466 | 3 | __m128i ff = _mm_set1_epi16(0x00FF); | |
| 467 | |||
| 468 | 3 | constexpr int rounder = 128; | |
| 469 | 3 | const __m128i rounder_simd = _mm_set1_epi16(rounder); | |
| 470 | |||
| 471 |
2/4void layer_rgb32_subtract_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 80 → 23 taken 11 times.
✓ Branch 80 → 81 taken 3 times.
void layer_rgb32_subtract_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✗ Branch 73 → 23 not taken.
✗ Branch 73 → 74 not taken.
|
14 | for (int y = 0; y < height; ++y) { |
| 472 |
2/4void layer_rgb32_subtract_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 75 → 24 taken 48 times.
✓ Branch 75 → 76 taken 11 times.
void layer_rgb32_subtract_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✗ Branch 68 → 24 not taken.
✗ Branch 68 → 69 not taken.
|
59 | for (int x = 0; x < mod2_width; x += 2) { |
| 473 | 48 | __m128i src = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(dstp + x * 4)); | |
| 474 | 96 | __m128i ovr = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(ovrp + x * 4)); | |
| 475 | |||
| 476 | 48 | __m128i alpha = calculate_monochrome_alpha_sse2(ovr, level_vector, one); | |
| 477 | |||
| 478 | 48 | src = _mm_unpacklo_epi8(src, zero); | |
| 479 | 96 | ovr = _mm_unpacklo_epi8(ovr, zero); | |
| 480 | |||
| 481 | __m128i luma; | ||
| 482 | if (use_chroma) { | ||
| 483 | ✗ | luma = _mm_subs_epi16(ff, ovr); | |
| 484 | } | ||
| 485 | else { | ||
| 486 | 144 | luma = calculate_luma_sse2(_mm_andnot_si128(ovr, ff), rgb_coeffs, zero); | |
| 487 | } | ||
| 488 | |||
| 489 | 48 | __m128i dst = _mm_subs_epi16(luma, src); | |
| 490 | 48 | dst = _mm_mullo_epi16(dst, alpha); | |
| 491 | 48 | dst = _mm_add_epi16(dst, rounder_simd); | |
| 492 | 48 | dst = _mm_srli_epi16(dst, 8); | |
| 493 | 48 | dst = _mm_add_epi8(src, dst); | |
| 494 | |||
| 495 | 48 | dst = _mm_packus_epi16(dst, zero); | |
| 496 | |||
| 497 | 48 | _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + x * 4), dst); | |
| 498 | } | ||
| 499 | |||
| 500 |
1/4void layer_rgb32_subtract_sse2<false>(unsigned char*, unsigned char const*, int, int, int, int, int):
✓ Branch 76 → 77 taken 11 times.
✗ Branch 76 → 79 not taken.
void layer_rgb32_subtract_sse2<true>(unsigned char*, unsigned char const*, int, int, int, int, int):
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 72 not taken.
|
11 | if (width != mod2_width) { |
| 501 | 11 | int x = mod2_width; | |
| 502 | 11 | int alpha = (ovrp[x * 4 + 3] * level + 1) >> 8; | |
| 503 | |||
| 504 | if (use_chroma) { | ||
| 505 | ✗ | dstp[x * 4] = dstp[x * 4] + (((255 - ovrp[x * 4] - dstp[x * 4]) * alpha + rounder) >> 8); | |
| 506 | ✗ | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((255 - ovrp[x * 4 + 1] - dstp[x * 4 + 1]) * alpha + rounder) >> 8); | |
| 507 | ✗ | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((255 - ovrp[x * 4 + 2] - dstp[x * 4 + 2]) * alpha + rounder) >> 8); | |
| 508 | ✗ | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((255 - ovrp[x * 4 + 3] - dstp[x * 4 + 3]) * alpha + rounder) >> 8); | |
| 509 | } | ||
| 510 | else { | ||
| 511 | 11 | int luma = (cyb * (255 - ovrp[x * 4]) + cyg * (255 - ovrp[x * 4 + 1]) + cyr * (255 - ovrp[x * 4 + 2])) >> 15; | |
| 512 | |||
| 513 | 11 | dstp[x * 4] = dstp[x * 4] + (((luma - dstp[x * 4]) * alpha + rounder) >> 8); | |
| 514 | 11 | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((luma - dstp[x * 4 + 1]) * alpha + rounder) >> 8); | |
| 515 | 11 | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((luma - dstp[x * 4 + 2]) * alpha + rounder) >> 8); | |
| 516 | 11 | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((luma - dstp[x * 4 + 3]) * alpha + rounder) >> 8); | |
| 517 | } | ||
| 518 | } | ||
| 519 | |||
| 520 | 11 | dstp += dst_pitch; | |
| 521 | 11 | ovrp += overlay_pitch; | |
| 522 | } | ||
| 523 | 3 | } | |
| 524 | |||
| 525 | // instantiate | ||
| 526 | template void layer_rgb32_subtract_sse2<false>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 527 | template void layer_rgb32_subtract_sse2<true>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level); | ||
| 528 | |||
| 529 | |||
| 530 | template<int mode> | ||
| 531 | 6 | void layer_rgb32_lighten_darken_sse2(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level, int thresh) { | |
| 532 | 6 | int mod2_width = width / 2 * 2; | |
| 533 | |||
| 534 | 6 | __m128i zero = _mm_setzero_si128(); | |
| 535 | 6 | __m128i level_vector = _mm_set1_epi32(level); | |
| 536 | 6 | __m128i one = _mm_set1_epi32(1); | |
| 537 | 6 | __m128i rgb_coeffs = _mm_set_epi16(0, cyr, cyg, cyb, 0, cyr, cyg, cyb); | |
| 538 | 6 | __m128i threshold = _mm_set1_epi16(thresh); | |
| 539 | |||
| 540 | 6 | constexpr int rounder = 128; | |
| 541 | 6 | const __m128i rounder_simd = _mm_set1_epi16(rounder); | |
| 542 | |||
| 543 |
4/4void layer_rgb32_lighten_darken_sse2<0>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 93 → 23 taken 11 times.
✓ Branch 93 → 94 taken 3 times.
void layer_rgb32_lighten_darken_sse2<1>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 93 → 23 taken 11 times.
✓ Branch 93 → 94 taken 3 times.
|
28 | for (int y = 0; y < height; ++y) { |
| 544 |
4/4void layer_rgb32_lighten_darken_sse2<0>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 86 → 24 taken 48 times.
✓ Branch 86 → 87 taken 11 times.
void layer_rgb32_lighten_darken_sse2<1>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 86 → 24 taken 48 times.
✓ Branch 86 → 87 taken 11 times.
|
118 | for (int x = 0; x < mod2_width; x += 2) { |
| 545 | 96 | __m128i src = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(dstp + x * 4)); | |
| 546 | 192 | __m128i ovr = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(ovrp + x * 4)); | |
| 547 | |||
| 548 | 96 | __m128i alpha = calculate_monochrome_alpha_sse2(ovr, level_vector, one); | |
| 549 | |||
| 550 | 96 | src = _mm_unpacklo_epi8(src, zero); | |
| 551 | 192 | ovr = _mm_unpacklo_epi8(ovr, zero); | |
| 552 | |||
| 553 | 96 | __m128i luma_ovr = calculate_luma_sse2(ovr, rgb_coeffs, zero); | |
| 554 | 96 | __m128i luma_src = calculate_luma_sse2(src, rgb_coeffs, zero); | |
| 555 | |||
| 556 | __m128i mask; | ||
| 557 | if constexpr (mode == LIGHTEN) { | ||
| 558 | 48 | __m128i tmp = _mm_add_epi16(luma_src, threshold); | |
| 559 | 48 | mask = _mm_cmpgt_epi16(luma_ovr, tmp); | |
| 560 | } | ||
| 561 | else { | ||
| 562 | 48 | __m128i tmp = _mm_sub_epi16(luma_src, threshold); | |
| 563 | 48 | mask = _mm_cmpgt_epi16(tmp, luma_ovr); | |
| 564 | } | ||
| 565 | |||
| 566 | 96 | alpha = _mm_and_si128(alpha, mask); | |
| 567 | |||
| 568 | 192 | __m128i dst = _mm_subs_epi16(ovr, src); | |
| 569 | 96 | dst = _mm_mullo_epi16(dst, alpha); | |
| 570 | 96 | dst = _mm_add_epi16(dst, rounder_simd); | |
| 571 | 96 | dst = _mm_srli_epi16(dst, 8); | |
| 572 | 96 | dst = _mm_add_epi8(src, dst); | |
| 573 | |||
| 574 | 96 | dst = _mm_packus_epi16(dst, zero); | |
| 575 | |||
| 576 | 96 | _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + x * 4), dst); | |
| 577 | } | ||
| 578 | |||
| 579 |
2/4void layer_rgb32_lighten_darken_sse2<0>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 87 → 88 taken 11 times.
✗ Branch 87 → 92 not taken.
void layer_rgb32_lighten_darken_sse2<1>(unsigned char*, unsigned char const*, int, int, int, int, int, int):
✓ Branch 87 → 88 taken 11 times.
✗ Branch 87 → 92 not taken.
|
22 | if (width != mod2_width) { |
| 580 | 22 | int x = mod2_width; | |
| 581 | 22 | int alpha = (ovrp[x * 4 + 3] * level + 1) >> 8; | |
| 582 | 22 | int luma_ovr = (cyb * ovrp[x * 4] + cyg * ovrp[x * 4 + 1] + cyr * ovrp[x * 4 + 2]) >> 15; | |
| 583 | 22 | int luma_src = (cyb * dstp[x * 4] + cyg * dstp[x * 4 + 1] + cyr * dstp[x * 4 + 2]) >> 15; | |
| 584 | |||
| 585 | if constexpr (mode == LIGHTEN) | ||
| 586 |
2/2✓ Branch 88 → 89 taken 1 time.
✓ Branch 88 → 90 taken 10 times.
|
11 | alpha = luma_ovr > luma_src + thresh ? alpha : 0; |
| 587 | else // DARKEN | ||
| 588 |
2/2✓ Branch 88 → 89 taken 5 times.
✓ Branch 88 → 90 taken 6 times.
|
11 | alpha = luma_ovr < luma_src - thresh ? alpha : 0; |
| 589 | |||
| 590 | 22 | dstp[x * 4] = dstp[x * 4] + (((ovrp[x * 4] - dstp[x * 4]) * alpha + rounder) >> 8); | |
| 591 | 22 | dstp[x * 4 + 1] = dstp[x * 4 + 1] + (((ovrp[x * 4 + 1] - dstp[x * 4 + 1]) * alpha + rounder) >> 8); | |
| 592 | 22 | dstp[x * 4 + 2] = dstp[x * 4 + 2] + (((ovrp[x * 4 + 2] - dstp[x * 4 + 2]) * alpha + rounder) >> 8); | |
| 593 | 22 | dstp[x * 4 + 3] = dstp[x * 4 + 3] + (((ovrp[x * 4 + 3] - dstp[x * 4 + 3]) * alpha + rounder) >> 8); | |
| 594 | } | ||
| 595 | |||
| 596 | 22 | dstp += dst_pitch; | |
| 597 | 22 | ovrp += overlay_pitch; | |
| 598 | } | ||
| 599 | 6 | } | |
| 600 | |||
| 601 | // instantiate | ||
| 602 | template void layer_rgb32_lighten_darken_sse2<LIGHTEN>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level, int thresh); | ||
| 603 | template void layer_rgb32_lighten_darken_sse2<DARKEN>(BYTE* dstp, const BYTE* ovrp, int dst_pitch, int overlay_pitch, int width, int height, int level, int thresh); | ||
| 604 | |||
| 605 |