filters/intel/merge_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 | // Avisynth filter: YUV merge / Swap planes | ||
| 37 | // by Klaus Post (kp@interact.dk) | ||
| 38 | // adapted by Richard Berg (avisynth-dev@richardberg.net) | ||
| 39 | // iSSE code by Ian Brabham | ||
| 40 | |||
| 41 | |||
| 42 | #include "../merge.h" | ||
| 43 | #include "merge_sse.h" | ||
| 44 | #include "merge_avx2.h" | ||
| 45 | #include "../core/internal.h" | ||
| 46 | |||
| 47 | // Intrinsics base header + really required extension headers | ||
| 48 | #if defined(_MSC_VER) | ||
| 49 | #include <intrin.h> // MSVC | ||
| 50 | #else | ||
| 51 | #include <x86intrin.h> // GCC/MinGW/Clang/LLVM | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #include "avs/alignment.h" | ||
| 55 | #include <stdint.h> | ||
| 56 | |||
| 57 | |||
| 58 | /* ----------------------------------- | ||
| 59 | * weighted_merge_chroma_yuy2 | ||
| 60 | * ----------------------------------- | ||
| 61 | */ | ||
| 62 | 2 | void weighted_merge_chroma_yuy2_sse2(BYTE *src, const BYTE *chroma, int pitch, int chroma_pitch,int width, int height, int weight, int invweight ) | |
| 63 | { | ||
| 64 | 2 | __m128i round_mask = _mm_set1_epi32(0x4000); | |
| 65 | 4 | __m128i mask = _mm_set_epi16(weight, invweight, weight, invweight, weight, invweight, weight, invweight); | |
| 66 | 2 | __m128i luma_mask = _mm_set1_epi16(0x00FF); | |
| 67 | |||
| 68 | 2 | int wMod16 = (width/16) * 16; | |
| 69 | |||
| 70 |
2/2✓ Branch 53 → 13 taken 18 times.
✓ Branch 53 → 54 taken 2 times.
|
20 | for (int y = 0; y < height; y++) { |
| 71 |
2/2✓ Branch 48 → 14 taken 47 times.
✓ Branch 48 → 49 taken 18 times.
|
65 | for (int x = 0; x < wMod16; x += 16) { |
| 72 | 47 | __m128i px1 = _mm_load_si128(reinterpret_cast<const __m128i*>(src+x)); | |
| 73 | 94 | __m128i px2 = _mm_load_si128(reinterpret_cast<const __m128i*>(chroma+x)); | |
| 74 | |||
| 75 | 47 | __m128i src_lo = _mm_unpacklo_epi16(px1, px2); | |
| 76 | 47 | __m128i src_hi = _mm_unpackhi_epi16(px1, px2); | |
| 77 | |||
| 78 | 47 | src_lo = _mm_srli_epi16(src_lo, 8); | |
| 79 | 47 | src_hi = _mm_srli_epi16(src_hi, 8); | |
| 80 | |||
| 81 | 47 | src_lo = _mm_madd_epi16(src_lo, mask); | |
| 82 | 47 | src_hi = _mm_madd_epi16(src_hi, mask); | |
| 83 | |||
| 84 | 47 | src_lo = _mm_add_epi32(src_lo, round_mask); | |
| 85 | 47 | src_hi = _mm_add_epi32(src_hi, round_mask); | |
| 86 | |||
| 87 | 47 | src_lo = _mm_srli_epi32(src_lo, 15); | |
| 88 | 47 | src_hi = _mm_srli_epi32(src_hi, 15); | |
| 89 | |||
| 90 | 47 | __m128i result_chroma = _mm_packs_epi32(src_lo, src_hi); | |
| 91 | 47 | result_chroma = _mm_slli_epi16(result_chroma, 8); | |
| 92 | |||
| 93 | 47 | __m128i result_luma = _mm_and_si128(px1, luma_mask); | |
| 94 | 47 | __m128i result = _mm_or_si128(result_chroma, result_luma); | |
| 95 | |||
| 96 | 47 | _mm_store_si128(reinterpret_cast<__m128i*>(src+x), result); | |
| 97 | } | ||
| 98 | |||
| 99 |
2/2✓ Branch 51 → 50 taken 98 times.
✓ Branch 51 → 52 taken 18 times.
|
116 | for (int x = wMod16; x < width; x+=2) { |
| 100 | 98 | src[x+1] = (chroma[x+1] * weight + src[x+1] * invweight + 16384) >> 15; | |
| 101 | } | ||
| 102 | |||
| 103 | 18 | src += pitch; | |
| 104 | 18 | chroma += chroma_pitch; | |
| 105 | } | ||
| 106 | 2 | } | |
| 107 | |||
| 108 | #ifdef X86_32 | ||
| 109 | void weighted_merge_chroma_yuy2_mmx(BYTE *src, const BYTE *chroma, int pitch, int chroma_pitch,int width, int height, int weight, int invweight ) | ||
| 110 | { | ||
| 111 | __m64 round_mask = _mm_set1_pi32(0x4000); | ||
| 112 | __m64 mask = _mm_set_pi16(weight, invweight, weight, invweight); | ||
| 113 | __m64 luma_mask = _mm_set1_pi16(0x00FF); | ||
| 114 | |||
| 115 | int wMod8 = (width/8) * 8; | ||
| 116 | |||
| 117 | for (int y = 0; y < height; y++) { | ||
| 118 | for (int x = 0; x < wMod8; x += 8) { | ||
| 119 | __m64 px1 = *reinterpret_cast<const __m64*>(src+x); //V1 Y3 U1 Y2 V0 Y1 U0 Y0 | ||
| 120 | __m64 px2 = *reinterpret_cast<const __m64*>(chroma+x); //v1 y3 u1 y2 v0 y1 u0 y0 | ||
| 121 | |||
| 122 | __m64 src_lo = _mm_unpacklo_pi16(px1, px2); //v0 y1 V0 Y1 u0 y0 U0 Y0 | ||
| 123 | __m64 src_hi = _mm_unpackhi_pi16(px1, px2); | ||
| 124 | |||
| 125 | src_lo = _mm_srli_pi16(src_lo, 8); //00 v0 00 V0 00 u0 00 U0 | ||
| 126 | src_hi = _mm_srli_pi16(src_hi, 8); | ||
| 127 | |||
| 128 | src_lo = _mm_madd_pi16(src_lo, mask); | ||
| 129 | src_hi = _mm_madd_pi16(src_hi, mask); | ||
| 130 | |||
| 131 | src_lo = _mm_add_pi32(src_lo, round_mask); | ||
| 132 | src_hi = _mm_add_pi32(src_hi, round_mask); | ||
| 133 | |||
| 134 | src_lo = _mm_srli_pi32(src_lo, 15); | ||
| 135 | src_hi = _mm_srli_pi32(src_hi, 15); | ||
| 136 | |||
| 137 | __m64 result_chroma = _mm_packs_pi32(src_lo, src_hi); | ||
| 138 | result_chroma = _mm_slli_pi16(result_chroma, 8); | ||
| 139 | |||
| 140 | __m64 result_luma = _mm_and_si64(px1, luma_mask); | ||
| 141 | __m64 result = _mm_or_si64(result_chroma, result_luma); | ||
| 142 | |||
| 143 | *reinterpret_cast<__m64*>(src+x) = result; | ||
| 144 | } | ||
| 145 | |||
| 146 | for (int x = wMod8; x < width; x+=2) { | ||
| 147 | src[x+1] = (chroma[x+1] * weight + src[x+1] * invweight + 16384) >> 15; | ||
| 148 | } | ||
| 149 | |||
| 150 | src += pitch; | ||
| 151 | chroma += chroma_pitch; | ||
| 152 | } | ||
| 153 | _mm_empty(); | ||
| 154 | } | ||
| 155 | #endif | ||
| 156 | |||
| 157 | |||
| 158 | |||
| 159 | /* ----------------------------------- | ||
| 160 | * weighted_merge_luma_yuy2 | ||
| 161 | * ----------------------------------- | ||
| 162 | */ | ||
| 163 | 2 | void weighted_merge_luma_yuy2_sse2(BYTE *src, const BYTE *luma, int pitch, int luma_pitch,int width, int height, int weight, int invweight) | |
| 164 | { | ||
| 165 | 2 | __m128i round_mask = _mm_set1_epi32(0x4000); | |
| 166 | 4 | __m128i mask = _mm_set_epi16(weight, invweight, weight, invweight, weight, invweight, weight, invweight); | |
| 167 | 2 | __m128i luma_mask = _mm_set1_epi16(0x00FF); | |
| 168 | 2 | __m128i chroma_mask = _mm_set1_epi16((short)0xFF00); | |
| 169 | |||
| 170 | 2 | int wMod16 = (width/16) * 16; | |
| 171 | |||
| 172 |
2/2✓ Branch 55 → 17 taken 18 times.
✓ Branch 55 → 56 taken 2 times.
|
20 | for (int y = 0; y < height; y++) { |
| 173 |
2/2✓ Branch 50 → 18 taken 47 times.
✓ Branch 50 → 51 taken 18 times.
|
65 | for (int x = 0; x < wMod16; x += 16) { |
| 174 | 47 | __m128i px1 = _mm_load_si128(reinterpret_cast<const __m128i*>(src+x)); //V1 Y3 U1 Y2 V0 Y1 U0 Y0 | |
| 175 | 94 | __m128i px2 = _mm_load_si128(reinterpret_cast<const __m128i*>(luma+x)); //v1 y3 u1 y2 v0 y1 u0 y0 | |
| 176 | |||
| 177 | 47 | __m128i src_lo = _mm_unpacklo_epi16(px1, px2); //v0 y1 V0 Y1 u0 y0 U0 Y0 | |
| 178 | 47 | __m128i src_hi = _mm_unpackhi_epi16(px1, px2); | |
| 179 | |||
| 180 | 47 | src_lo = _mm_and_si128(src_lo, luma_mask); //00 v0 00 V0 00 u0 00 U0 | |
| 181 | 47 | src_hi = _mm_and_si128(src_hi, luma_mask); | |
| 182 | |||
| 183 | 47 | src_lo = _mm_madd_epi16(src_lo, mask); | |
| 184 | 47 | src_hi = _mm_madd_epi16(src_hi, mask); | |
| 185 | |||
| 186 | 47 | src_lo = _mm_add_epi32(src_lo, round_mask); | |
| 187 | 47 | src_hi = _mm_add_epi32(src_hi, round_mask); | |
| 188 | |||
| 189 | 47 | src_lo = _mm_srli_epi32(src_lo, 15); | |
| 190 | 47 | src_hi = _mm_srli_epi32(src_hi, 15); | |
| 191 | |||
| 192 | 47 | __m128i result_luma = _mm_packs_epi32(src_lo, src_hi); | |
| 193 | |||
| 194 | 47 | __m128i result_chroma = _mm_and_si128(px1, chroma_mask); | |
| 195 | 47 | __m128i result = _mm_or_si128(result_chroma, result_luma); | |
| 196 | |||
| 197 | 47 | _mm_store_si128(reinterpret_cast<__m128i*>(src+x), result); | |
| 198 | } | ||
| 199 | |||
| 200 |
2/2✓ Branch 53 → 52 taken 98 times.
✓ Branch 53 → 54 taken 18 times.
|
116 | for (int x = wMod16; x < width; x+=2) { |
| 201 | 98 | src[x] = (luma[x] * weight + src[x] * invweight + 16384) >> 15; | |
| 202 | } | ||
| 203 | |||
| 204 | 18 | src += pitch; | |
| 205 | 18 | luma += luma_pitch; | |
| 206 | } | ||
| 207 | 2 | } | |
| 208 | |||
| 209 | #ifdef X86_32 | ||
| 210 | void weighted_merge_luma_yuy2_mmx(BYTE *src, const BYTE *luma, int pitch, int luma_pitch,int width, int height, int weight, int invweight) | ||
| 211 | { | ||
| 212 | __m64 round_mask = _mm_set1_pi32(0x4000); | ||
| 213 | __m64 mask = _mm_set_pi16(weight, invweight, weight, invweight); | ||
| 214 | __m64 luma_mask = _mm_set1_pi16(0x00FF); | ||
| 215 | __m64 chroma_mask = _mm_set1_pi16((short)0xFF00); | ||
| 216 | |||
| 217 | int wMod8 = (width/8) * 8; | ||
| 218 | |||
| 219 | for (int y = 0; y < height; y++) { | ||
| 220 | for (int x = 0; x < wMod8; x += 8) { | ||
| 221 | __m64 px1 = *reinterpret_cast<const __m64*>(src+x); //V1 Y3 U1 Y2 V0 Y1 U0 Y0 | ||
| 222 | __m64 px2 = *reinterpret_cast<const __m64*>(luma+x); //v1 y3 u1 y2 v0 y1 u0 y0 | ||
| 223 | |||
| 224 | __m64 src_lo = _mm_unpacklo_pi16(px1, px2); //v0 y1 V0 Y1 u0 y0 U0 Y0 | ||
| 225 | __m64 src_hi = _mm_unpackhi_pi16(px1, px2); | ||
| 226 | |||
| 227 | src_lo = _mm_and_si64(src_lo, luma_mask); //00 v0 00 V0 00 u0 00 U0 | ||
| 228 | src_hi = _mm_and_si64(src_hi, luma_mask); | ||
| 229 | |||
| 230 | src_lo = _mm_madd_pi16(src_lo, mask); | ||
| 231 | src_hi = _mm_madd_pi16(src_hi, mask); | ||
| 232 | |||
| 233 | src_lo = _mm_add_pi32(src_lo, round_mask); | ||
| 234 | src_hi = _mm_add_pi32(src_hi, round_mask); | ||
| 235 | |||
| 236 | src_lo = _mm_srli_pi32(src_lo, 15); | ||
| 237 | src_hi = _mm_srli_pi32(src_hi, 15); | ||
| 238 | |||
| 239 | __m64 result_luma = _mm_packs_pi32(src_lo, src_hi); | ||
| 240 | |||
| 241 | __m64 result_chroma = _mm_and_si64(px1, chroma_mask); | ||
| 242 | __m64 result = _mm_or_si64(result_chroma, result_luma); | ||
| 243 | |||
| 244 | *reinterpret_cast<__m64*>(src+x) = result; | ||
| 245 | } | ||
| 246 | |||
| 247 | for (int x = wMod8; x < width; x+=2) { | ||
| 248 | src[x] = (luma[x] * weight + src[x] * invweight + 16384) >> 15; | ||
| 249 | } | ||
| 250 | |||
| 251 | src += pitch; | ||
| 252 | luma += luma_pitch; | ||
| 253 | } | ||
| 254 | _mm_empty(); | ||
| 255 | } | ||
| 256 | #endif | ||
| 257 | |||
| 258 | |||
| 259 | /* ----------------------------------- | ||
| 260 | * replace_luma_yuy2 | ||
| 261 | * ----------------------------------- | ||
| 262 | */ | ||
| 263 | 2 | void replace_luma_yuy2_sse2(BYTE *src, const BYTE *luma, int pitch, int luma_pitch,int width, int height) | |
| 264 | { | ||
| 265 | 2 | int mod16_width = width / 16 * 16; | |
| 266 | 2 | __m128i luma_mask = _mm_set1_epi16(0x00FF); | |
| 267 | 2 | __m128i chroma_mask = _mm_set1_epi16((short)0xFF00); | |
| 268 | |||
| 269 |
2/2✓ Branch 29 → 11 taken 18 times.
✓ Branch 29 → 30 taken 2 times.
|
20 | for(int y = 0; y < height; y++) { |
| 270 |
2/2✓ Branch 24 → 12 taken 47 times.
✓ Branch 24 → 25 taken 18 times.
|
65 | for(int x = 0; x < mod16_width; x+=16) { |
| 271 | 47 | __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(src+x)); | |
| 272 | 94 | __m128i l = _mm_load_si128(reinterpret_cast<const __m128i*>(luma+x)); | |
| 273 | |||
| 274 | 47 | __m128i s_chroma = _mm_and_si128(s, chroma_mask); | |
| 275 | 47 | __m128i l_luma = _mm_and_si128(l, luma_mask); | |
| 276 | |||
| 277 | 47 | __m128i result = _mm_or_si128(s_chroma, l_luma); | |
| 278 | |||
| 279 | 47 | _mm_store_si128(reinterpret_cast<__m128i*>(src+x), result); | |
| 280 | } | ||
| 281 | |||
| 282 |
2/2✓ Branch 27 → 26 taken 98 times.
✓ Branch 27 → 28 taken 18 times.
|
116 | for (int x = mod16_width; x < width; x+=2) { |
| 283 | 98 | src[x] = luma[x]; | |
| 284 | } | ||
| 285 | 18 | src += pitch; | |
| 286 | 18 | luma += luma_pitch; | |
| 287 | } | ||
| 288 | 2 | } | |
| 289 | |||
| 290 | #ifdef X86_32 | ||
| 291 | void replace_luma_yuy2_mmx(BYTE *src, const BYTE *luma, int pitch, int luma_pitch,int width, int height) | ||
| 292 | { | ||
| 293 | int mod8_width = width / 8 * 8; | ||
| 294 | __m64 luma_mask = _mm_set1_pi16(0x00FF); | ||
| 295 | __m64 chroma_mask = _mm_set1_pi16((short)0xFF00); | ||
| 296 | |||
| 297 | for(int y = 0; y < height; y++) { | ||
| 298 | for(int x = 0; x < mod8_width; x+=8) { | ||
| 299 | __m64 s = *reinterpret_cast<const __m64*>(src+x); | ||
| 300 | __m64 l = *reinterpret_cast<const __m64*>(luma+x); | ||
| 301 | |||
| 302 | __m64 s_chroma = _mm_and_si64(s, chroma_mask); | ||
| 303 | __m64 l_luma = _mm_and_si64(l, luma_mask); | ||
| 304 | |||
| 305 | __m64 result = _mm_or_si64(s_chroma, l_luma); | ||
| 306 | |||
| 307 | *reinterpret_cast<__m64*>(src+x) = result; | ||
| 308 | } | ||
| 309 | |||
| 310 | for (int x = mod8_width; x < width; x+=2) { | ||
| 311 | src[x] = luma[x]; | ||
| 312 | } | ||
| 313 | src += pitch; | ||
| 314 | luma += luma_pitch; | ||
| 315 | } | ||
| 316 | _mm_empty(); | ||
| 317 | } | ||
| 318 | #endif | ||
| 319 | |||
| 320 | |||
| 321 | |||
| 322 | /* ----------------------------------- | ||
| 323 | * average_plane | ||
| 324 | * ----------------------------------- | ||
| 325 | */ | ||
| 326 | // Can be called from Layer or Overlay, so no aligned loads/stores here and prepare for exact width | ||
| 327 | template<typename pixel_t> | ||
| 328 | 6 | void average_plane_sse2(BYTE *p1, const BYTE *p2, int p1_pitch, int p2_pitch, int rowsize, int height) { | |
| 329 | // width is RowSize here | ||
| 330 | 6 | int mod16_width = rowsize / 16 * 16; | |
| 331 | |||
| 332 |
4/4void average_plane_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 18 → 3 taken 15 times.
✓ Branch 18 → 19 taken 3 times.
void average_plane_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 18 → 3 taken 15 times.
✓ Branch 18 → 19 taken 3 times.
|
36 | for(int y = 0; y < height; y++) { |
| 333 |
4/4void average_plane_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 12 → 4 taken 37 times.
✓ Branch 12 → 13 taken 15 times.
void average_plane_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 12 → 4 taken 37 times.
✓ Branch 12 → 13 taken 15 times.
|
104 | for(int x = 0; x < mod16_width; x+=16) { |
| 334 | 74 | __m128i src1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p1+x)); | |
| 335 | 148 | __m128i src2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p2+x)); | |
| 336 | __m128i dst; | ||
| 337 | if constexpr(sizeof(pixel_t) == 1) | ||
| 338 | 37 | dst = _mm_avg_epu8(src1, src2); // 8 pixels | |
| 339 | else // pixel_size == 2 | ||
| 340 | 37 | dst = _mm_avg_epu16(src1, src2); // 4 pixels | |
| 341 | |||
| 342 | 74 | _mm_storeu_si128(reinterpret_cast<__m128i*>(p1+x), dst); | |
| 343 | } | ||
| 344 | |||
| 345 |
4/4void average_plane_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 13 → 14 taken 12 times.
✓ Branch 13 → 17 taken 3 times.
void average_plane_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 13 → 14 taken 12 times.
✓ Branch 13 → 17 taken 3 times.
|
30 | if (mod16_width != rowsize) { |
| 346 |
4/4void average_plane_sse2<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 16 → 15 taken 110 times.
✓ Branch 16 → 17 taken 12 times.
void average_plane_sse2<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 16 → 15 taken 56 times.
✓ Branch 16 → 17 taken 12 times.
|
190 | for (size_t x = mod16_width / sizeof(pixel_t); x < rowsize/sizeof(pixel_t); ++x) { |
| 347 | 166 | reinterpret_cast<pixel_t *>(p1)[x] = (int(reinterpret_cast<pixel_t *>(p1)[x]) + reinterpret_cast<const pixel_t *>(p2)[x] + 1) >> 1; | |
| 348 | } | ||
| 349 | } | ||
| 350 | 30 | p1 += p1_pitch; | |
| 351 | 30 | p2 += p2_pitch; | |
| 352 | } | ||
| 353 | 6 | } | |
| 354 | |||
| 355 | // instantiate | ||
| 356 | template void average_plane_sse2<uint8_t>(BYTE* p1, const BYTE* p2, int p1_pitch, int p2_pitch, int rowsize, int height); | ||
| 357 | template void average_plane_sse2<uint16_t>(BYTE* p1, const BYTE* p2, int p1_pitch, int p2_pitch, int rowsize, int height); | ||
| 358 | |||
| 359 | // weighted_merge_planar SSE2 implementations moved to overlay/intel/blend_common_sse.cpp | ||
| 360 | // (see weighted_merge_sse2 / weighted_merge_float_sse2) | ||
| 361 | |||
| 362 | 3 | void average_plane_sse2_float(BYTE *p1, const BYTE *p2, int p1_pitch, int p2_pitch, int rowsize, int height) { | |
| 363 | 3 | auto OneHalf = _mm_set1_ps(0.5f); | |
| 364 | |||
| 365 | 3 | int wMod16 = (rowsize / 16) * 16; | |
| 366 | |||
| 367 |
2/2✓ Branch 21 → 5 taken 15 times.
✓ Branch 21 → 22 taken 3 times.
|
18 | for (int y = 0; y < height; y++) { |
| 368 |
2/2✓ Branch 16 → 6 taken 67 times.
✓ Branch 16 → 17 taken 15 times.
|
82 | for (int x = 0; x < wMod16; x += 16) { |
| 369 | 67 | auto px1 = _mm_loadu_ps(reinterpret_cast<const float*>(p1 + x)); | |
| 370 | 134 | auto px2 = _mm_loadu_ps(reinterpret_cast<const float*>(p2 + x)); | |
| 371 | |||
| 372 | 67 | auto result = _mm_mul_ps(_mm_add_ps(px1, px2), OneHalf); | |
| 373 | |||
| 374 | 67 | _mm_storeu_ps(reinterpret_cast<float *>(p1 + x), result); | |
| 375 | } | ||
| 376 | |||
| 377 |
2/2✓ Branch 19 → 18 taken 12 times.
✓ Branch 19 → 20 taken 15 times.
|
27 | for (size_t x = wMod16 / sizeof(float); x < rowsize / sizeof(float); x++) { |
| 378 | 12 | reinterpret_cast<float *>(p1)[x] = (reinterpret_cast<float *>(p1)[x] + reinterpret_cast<const float *>(p2)[x]) * 0.5f; | |
| 379 | } | ||
| 380 | |||
| 381 | 15 | p1 += p1_pitch; | |
| 382 | 15 | p2 += p2_pitch; | |
| 383 | } | ||
| 384 | 3 | } | |
| 385 | |||
| 386 |