filters/intel/planeswap_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: Swap planes | ||
| 37 | // by Klaus Post | ||
| 38 | // adapted by Richard Berg (avisynth-dev@richardberg.net) | ||
| 39 | // iSSE code by Ian Brabham | ||
| 40 | |||
| 41 | #include <avs/config.h> | ||
| 42 | #ifdef AVS_WINDOWS | ||
| 43 | #include <avs/win.h> | ||
| 44 | #else | ||
| 45 | #include <avs/posix.h> | ||
| 46 | #endif | ||
| 47 | #include "planeswap_sse.h" | ||
| 48 | |||
| 49 | // Intrinsics base header + really required extension headers | ||
| 50 | #if defined(_MSC_VER) | ||
| 51 | #include <intrin.h> // MSVC | ||
| 52 | #else | ||
| 53 | #include <x86intrin.h> // GCC/MinGW/Clang/LLVM | ||
| 54 | #endif | ||
| 55 | #include <tmmintrin.h> // SSSE3 | ||
| 56 | |||
| 57 | #include "stdint.h" | ||
| 58 | #include <type_traits> | ||
| 59 | |||
| 60 | // --------------------------------------------------------------------------- | ||
| 61 | // Packed RGB32 channel extraction — SSE2, 16 pixels per iteration. | ||
| 62 | // | ||
| 63 | // Source layout (per pixel, 4 bytes): B G R A (channel_index: B=0 G=1 R=2 A=3) | ||
| 64 | // Source rows are bottom-up; srcp must already point at the last (bottom) row. | ||
| 65 | // Pitch is positive; we step backwards (srcp -= src_pitch) each row. | ||
| 66 | // | ||
| 67 | // Strategy: shift each 32-bit pixel right by channel_index*8, mask the low byte, | ||
| 68 | // pack 4+4+4+4 = 16 values through packs_epi32 + packus_epi16. | ||
| 69 | // Width is guaranteed a multiple of 16 (64-byte pitch / 4 bytes per pixel). | ||
| 70 | // --------------------------------------------------------------------------- | ||
| 71 | template<int channel_index> | ||
| 72 | 8 | void extract_packed_rgb32_channel_sse2( | |
| 73 | const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int width, int height) | ||
| 74 | { | ||
| 75 | 8 | const __m128i mask = _mm_set1_epi32(0xFF); | |
| 76 |
8/8void extract_packed_rgb32_channel_sse2<0>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 34 → 7 taken 12 times.
✓ Branch 34 → 35 taken 2 times.
void extract_packed_rgb32_channel_sse2<1>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 42 → 7 taken 12 times.
✓ Branch 42 → 43 taken 2 times.
void extract_packed_rgb32_channel_sse2<2>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 42 → 7 taken 12 times.
✓ Branch 42 → 43 taken 2 times.
void extract_packed_rgb32_channel_sse2<3>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 42 → 7 taken 12 times.
✓ Branch 42 → 43 taken 2 times.
|
56 | for (int y = 0; y < height; ++y) { |
| 77 |
8/8void extract_packed_rgb32_channel_sse2<0>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 32 → 8 taken 36 times.
✓ Branch 32 → 33 taken 12 times.
void extract_packed_rgb32_channel_sse2<1>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 40 → 8 taken 36 times.
✓ Branch 40 → 41 taken 12 times.
void extract_packed_rgb32_channel_sse2<2>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 40 → 8 taken 36 times.
✓ Branch 40 → 41 taken 12 times.
void extract_packed_rgb32_channel_sse2<3>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 40 → 8 taken 36 times.
✓ Branch 40 → 41 taken 12 times.
|
192 | for (int x = 0; x < width; x += 16) { |
| 78 | 144 | __m128i v0 = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 4 + 0)); | |
| 79 | 144 | __m128i v1 = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 4 + 16)); | |
| 80 | 144 | __m128i v2 = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 4 + 32)); | |
| 81 | 288 | __m128i v3 = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 4 + 48)); | |
| 82 | // Move requested byte to the low byte of each 32-bit dword | ||
| 83 | if constexpr (channel_index > 0) { | ||
| 84 | 108 | v0 = _mm_srli_epi32(v0, channel_index * 8); | |
| 85 | 108 | v1 = _mm_srli_epi32(v1, channel_index * 8); | |
| 86 | 108 | v2 = _mm_srli_epi32(v2, channel_index * 8); | |
| 87 | 108 | v3 = _mm_srli_epi32(v3, channel_index * 8); | |
| 88 | } | ||
| 89 | 144 | v0 = _mm_and_si128(v0, mask); | |
| 90 | 144 | v1 = _mm_and_si128(v1, mask); | |
| 91 | 144 | v2 = _mm_and_si128(v2, mask); | |
| 92 | 144 | v3 = _mm_and_si128(v3, mask); | |
| 93 | // Pack 4 × 32-bit (values 0-255) → 8 × 16-bit → 16 × 8-bit | ||
| 94 | 432 | _mm_store_si128(reinterpret_cast<__m128i*>(dstp + x), | |
| 95 | _mm_packus_epi16(_mm_packs_epi32(v0, v1), _mm_packs_epi32(v2, v3))); | ||
| 96 | } | ||
| 97 | 48 | srcp -= src_pitch; | |
| 98 | 48 | dstp += dst_pitch; | |
| 99 | } | ||
| 100 | 8 | } | |
| 101 | |||
| 102 | template void extract_packed_rgb32_channel_sse2<0>(const BYTE*, BYTE*, int, int, int, int); | ||
| 103 | template void extract_packed_rgb32_channel_sse2<1>(const BYTE*, BYTE*, int, int, int, int); | ||
| 104 | template void extract_packed_rgb32_channel_sse2<2>(const BYTE*, BYTE*, int, int, int, int); | ||
| 105 | template void extract_packed_rgb32_channel_sse2<3>(const BYTE*, BYTE*, int, int, int, int); | ||
| 106 | |||
| 107 | // --------------------------------------------------------------------------- | ||
| 108 | // Packed RGB64 channel extraction — SSE2, 8 pixels per iteration. | ||
| 109 | // | ||
| 110 | // Source layout (per pixel, 8 bytes): B G R A (uint16_t each; B=0 G=1 R=2 A=3) | ||
| 111 | // Source rows are bottom-up; srcp must already point at the last (bottom) row. | ||
| 112 | // | ||
| 113 | // Strategy: 3-stage deinterleave using unpacklo/hi_epi16, unpacklo/hi_epi32, | ||
| 114 | // unpacklo/hi_epi64, then unscramble with shufflelo/hi_epi16. | ||
| 115 | // | ||
| 116 | // Two register pairs (a,b) and (c,d) each hold 4 pixels: | ||
| 117 | // a = [B0 G0 R0 A0 | B1 G1 R1 A1] (pixel 0, pixel 1 — 8 uint16_t) | ||
| 118 | // b = [B2 G2 R2 A2 | B3 G3 R3 A3] | ||
| 119 | // c = pixels 4-5, d = pixels 6-7 | ||
| 120 | // | ||
| 121 | // After unpacklo_epi16(a,b): [B0 B2 | G0 G2 | R0 R2 | A0 A2] | ||
| 122 | // After unpackhi_epi16(a,b): [B1 B3 | G1 G3 | R1 R3 | A1 A3] | ||
| 123 | // unpacklo_epi32 of those: [B0 B2 B1 B3 | G0 G2 G1 G3] (ch 0,1 in lo/hi 64-bit lanes) | ||
| 124 | // unpackhi_epi32 of those: [R0 R2 R1 R3 | A0 A2 A1 A3] (ch 2,3 in lo/hi 64-bit lanes) | ||
| 125 | // unpacklo/hi_epi64 selects the right channel across both pairs → [C0 C2 C1 C3 | C4 C6 C5 C7] | ||
| 126 | // shufflelo + shufflehi with _MM_SHUFFLE(3,1,2,0) unscrambles to [C0 C1 C2 C3 | C4 C5 C6 C7]. | ||
| 127 | // | ||
| 128 | // Width is guaranteed a multiple of 8 (64-byte pitch / 8 bytes per pixel). | ||
| 129 | // --------------------------------------------------------------------------- | ||
| 130 | template<int channel_index> | ||
| 131 | 8 | void extract_packed_rgb64_channel_sse2( | |
| 132 | const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int width, int height) | ||
| 133 | { | ||
| 134 |
8/8void extract_packed_rgb64_channel_sse2<0>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 30 → 3 taken 12 times.
✓ Branch 30 → 31 taken 2 times.
void extract_packed_rgb64_channel_sse2<1>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 30 → 3 taken 12 times.
✓ Branch 30 → 31 taken 2 times.
void extract_packed_rgb64_channel_sse2<2>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 30 → 3 taken 12 times.
✓ Branch 30 → 31 taken 2 times.
void extract_packed_rgb64_channel_sse2<3>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 30 → 3 taken 12 times.
✓ Branch 30 → 31 taken 2 times.
|
56 | for (int y = 0; y < height; ++y) { |
| 135 |
8/8void extract_packed_rgb64_channel_sse2<0>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 28 → 4 taken 36 times.
✓ Branch 28 → 29 taken 12 times.
void extract_packed_rgb64_channel_sse2<1>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 28 → 4 taken 36 times.
✓ Branch 28 → 29 taken 12 times.
void extract_packed_rgb64_channel_sse2<2>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 28 → 4 taken 36 times.
✓ Branch 28 → 29 taken 12 times.
void extract_packed_rgb64_channel_sse2<3>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 28 → 4 taken 36 times.
✓ Branch 28 → 29 taken 12 times.
|
192 | for (int x = 0; x < width; x += 8) { |
| 136 | 144 | __m128i a = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 8 + 0)); // px 0-1 | |
| 137 | 144 | __m128i b = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 8 + 16)); // px 2-3 | |
| 138 | 144 | __m128i c = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 8 + 32)); // px 4-5 | |
| 139 | 288 | __m128i d = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x * 8 + 48)); // px 6-7 | |
| 140 | |||
| 141 | // Stage 1: interleave same-index pixels from each pair | ||
| 142 | // t0/t1 from pair (a,b); t4/t5 from pair (c,d) | ||
| 143 | 144 | __m128i t0 = _mm_unpacklo_epi16(a, b); // [B0 B2 | G0 G2 | R0 R2 | A0 A2] | |
| 144 | 144 | __m128i t1 = _mm_unpackhi_epi16(a, b); // [B1 B3 | G1 G3 | R1 R3 | A1 A3] | |
| 145 | 144 | __m128i t4 = _mm_unpacklo_epi16(c, d); // [B4 B6 | G4 G6 | R4 R6 | A4 A6] | |
| 146 | 144 | __m128i t5 = _mm_unpackhi_epi16(c, d); // [B5 B7 | G5 G7 | R5 R7 | A5 A7] | |
| 147 | |||
| 148 | // Stage 2: gather channel into 64-bit lanes | ||
| 149 | // ch 0,1: lo qword = channel ch%2==0, hi qword = channel ch%2==1 | ||
| 150 | // ch 2,3: same but from the hi 32-bit positions | ||
| 151 | __m128i lo, hi; | ||
| 152 | if constexpr (channel_index <= 1) { | ||
| 153 | 72 | lo = _mm_unpacklo_epi32(t0, t1); // [B0 B2 B1 B3 | G0 G2 G1 G3] | |
| 154 | 72 | hi = _mm_unpacklo_epi32(t4, t5); // [B4 B6 B5 B7 | G4 G6 G5 G7] | |
| 155 | } else { | ||
| 156 | 72 | lo = _mm_unpackhi_epi32(t0, t1); // [R0 R2 R1 R3 | A0 A2 A1 A3] | |
| 157 | 72 | hi = _mm_unpackhi_epi32(t4, t5); // [R4 R6 R5 R7 | A4 A6 A5 A7] | |
| 158 | } | ||
| 159 | |||
| 160 | // Stage 3: select even-indexed (ch 0,2) or odd-indexed (ch 1,3) channel lane | ||
| 161 | __m128i v; | ||
| 162 | if constexpr (channel_index == 0 || channel_index == 2) { | ||
| 163 | 72 | v = _mm_unpacklo_epi64(lo, hi); // [C0 C2 C1 C3 | C4 C6 C5 C7] | |
| 164 | } else { | ||
| 165 | 72 | v = _mm_unpackhi_epi64(lo, hi); // [C0 C2 C1 C3 | C4 C6 C5 C7] | |
| 166 | } | ||
| 167 | |||
| 168 | // Stage 4: unscramble [C0 C2 C1 C3 | C4 C6 C5 C7] → [C0 C1 C2 C3 | C4 C5 C6 C7] | ||
| 169 | 144 | v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(3,1,2,0)); | |
| 170 | 144 | v = _mm_shufflehi_epi16(v, _MM_SHUFFLE(3,1,2,0)); | |
| 171 | |||
| 172 | 144 | _mm_store_si128(reinterpret_cast<__m128i*>(dstp + x * 2), v); | |
| 173 | } | ||
| 174 | 48 | srcp -= src_pitch; | |
| 175 | 48 | dstp += dst_pitch; | |
| 176 | } | ||
| 177 | 8 | } | |
| 178 | |||
| 179 | template void extract_packed_rgb64_channel_sse2<0>(const BYTE*, BYTE*, int, int, int, int); | ||
| 180 | template void extract_packed_rgb64_channel_sse2<1>(const BYTE*, BYTE*, int, int, int, int); | ||
| 181 | template void extract_packed_rgb64_channel_sse2<2>(const BYTE*, BYTE*, int, int, int, int); | ||
| 182 | template void extract_packed_rgb64_channel_sse2<3>(const BYTE*, BYTE*, int, int, int, int); | ||
| 183 | |||
| 184 | |||
| 185 | |||
| 186 | /************************************** | ||
| 187 | * Swap - swaps UV on planar maps | ||
| 188 | **************************************/ | ||
| 189 | |||
| 190 | 2 | void yuy2_swap_sse2(const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int width, int height) | |
| 191 | { | ||
| 192 | 2 | const __m128i mask = _mm_set1_epi16(0x00FF); | |
| 193 | |||
| 194 |
2/2✓ Branch 20 → 7 taken 12 times.
✓ Branch 20 → 21 taken 2 times.
|
14 | for (int y = 0; y < height; ++y ) { |
| 195 |
2/2✓ Branch 18 → 8 taken 50 times.
✓ Branch 18 → 19 taken 12 times.
|
62 | for (int x = 0; x < width; x += 16) { |
| 196 | 50 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x)); | |
| 197 | 50 | __m128i swapped = _mm_shufflelo_epi16(src, _MM_SHUFFLE(2, 3, 0, 1)); | |
| 198 | 50 | swapped = _mm_shufflehi_epi16(swapped, _MM_SHUFFLE(2, 3, 0, 1)); | |
| 199 | 100 | swapped = _mm_or_si128(_mm_and_si128(mask, src), _mm_andnot_si128(mask, swapped)); | |
| 200 | 50 | _mm_stream_si128(reinterpret_cast<__m128i*>(dstp + x), swapped); | |
| 201 | } | ||
| 202 | |||
| 203 | 12 | dstp += dst_pitch; | |
| 204 | 12 | srcp += src_pitch; | |
| 205 | } | ||
| 206 | 2 | } | |
| 207 | |||
| 208 | #if defined(GCC) || defined(CLANG) | ||
| 209 | __attribute__((__target__("ssse3"))) | ||
| 210 | #endif | ||
| 211 | 2 | void yuy2_swap_ssse3(const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int width, int height) | |
| 212 | { | ||
| 213 | 2 | const __m128i mask = _mm_set_epi8(13, 14, 15, 12, 9, 10, 11, 8, 5, 6, 7, 4, 1, 2, 3, 0); | |
| 214 | |||
| 215 |
2/2✓ Branch 14 → 5 taken 12 times.
✓ Branch 14 → 15 taken 2 times.
|
14 | for (int y = 0; y < height; ++y) { |
| 216 |
2/2✓ Branch 12 → 6 taken 50 times.
✓ Branch 12 → 13 taken 12 times.
|
62 | for (int x = 0; x < width; x += 16) { |
| 217 | 100 | __m128i src = _mm_load_si128(reinterpret_cast<const __m128i*>(srcp + x)); | |
| 218 | 50 | __m128i dst = _mm_shuffle_epi8(src, mask); | |
| 219 | 50 | _mm_stream_si128(reinterpret_cast<__m128i*>(dstp + x), dst); | |
| 220 | } | ||
| 221 | |||
| 222 | 12 | dstp += dst_pitch; | |
| 223 | 12 | srcp += src_pitch; | |
| 224 | } | ||
| 225 | 2 | } | |
| 226 | |||
| 227 | #ifdef X86_32 | ||
| 228 | void yuy2_swap_isse(const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int width, int height) | ||
| 229 | { | ||
| 230 | __m64 mask = _mm_set1_pi16(0x00FF); | ||
| 231 | |||
| 232 | for (int y = 0; y < height; ++y) { | ||
| 233 | for (int x = 0; x < width; x+= 8) { | ||
| 234 | __m64 src = *reinterpret_cast<const __m64*>(srcp+x); | ||
| 235 | __m64 swapped = _mm_shuffle_pi16(src, _MM_SHUFFLE(2, 3, 0, 1)); | ||
| 236 | swapped = _mm_or_si64(_mm_and_si64(mask, src), _mm_andnot_si64(mask, swapped)); | ||
| 237 | *reinterpret_cast<__m64*>(dstp + x) = swapped; | ||
| 238 | } | ||
| 239 | |||
| 240 | dstp += dst_pitch; | ||
| 241 | srcp += src_pitch; | ||
| 242 | } | ||
| 243 | _mm_empty(); | ||
| 244 | } | ||
| 245 | #endif | ||
| 246 | |||
| 247 | 2 | void yuy2_uvtoy_sse2(const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int dst_width, int height, int pos) | |
| 248 | { | ||
| 249 | 2 | const __m128i chroma = _mm_set1_epi32(0x80008000); | |
| 250 | 2 | const __m128i mask = _mm_set1_epi32(0x000000FF); | |
| 251 | 2 | pos *= 8; | |
| 252 | |||
| 253 |
2/2✓ Branch 32 → 11 taken 10 times.
✓ Branch 32 → 33 taken 2 times.
|
12 | for (int y = 0; y < height; ++y) { |
| 254 |
2/2✓ Branch 30 → 12 taken 20 times.
✓ Branch 30 → 31 taken 10 times.
|
30 | for (int x = 0; x < dst_width; x += 16) { |
| 255 | 20 | __m128i s0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + 2 * x)); | |
| 256 | 40 | __m128i s1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + 2 * x + 16)); | |
| 257 | 40 | s0 = _mm_and_si128(mask, _mm_srli_epi32(s0, pos)); | |
| 258 | 40 | s1 = _mm_and_si128(mask, _mm_srli_epi32(s1, pos)); | |
| 259 | 20 | s0 = _mm_packs_epi32(s0, s1); | |
| 260 | 20 | s0 = _mm_or_si128(s0, chroma); | |
| 261 | 20 | _mm_stream_si128(reinterpret_cast<__m128i*>(dstp + x), s0); | |
| 262 | } | ||
| 263 | 10 | srcp += src_pitch; | |
| 264 | 10 | dstp += dst_pitch; | |
| 265 | } | ||
| 266 | 2 | } | |
| 267 | |||
| 268 | 2 | void yuy2_uvtoy8_sse2(const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int dst_width, int height, int pos) | |
| 269 | { | ||
| 270 | 2 | const __m128i mask = _mm_set1_epi32(0x000000FF); | |
| 271 | 2 | pos *= 8; | |
| 272 | |||
| 273 |
2/2✓ Branch 28 → 7 taken 10 times.
✓ Branch 28 → 29 taken 2 times.
|
12 | for (int y = 0; y < height; ++y) { |
| 274 |
2/2✓ Branch 26 → 8 taken 40 times.
✓ Branch 26 → 27 taken 10 times.
|
50 | for (int x = 0; x < dst_width; x += 8) { |
| 275 | 40 | __m128i s0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + 4 * x)); | |
| 276 | 80 | __m128i s1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + 4 * x + 16)); | |
| 277 | 80 | s0 = _mm_and_si128(mask, _mm_srli_epi32(s0, pos)); | |
| 278 | 80 | s1 = _mm_and_si128(mask, _mm_srli_epi32(s1, pos)); | |
| 279 | 40 | s0 = _mm_packs_epi32(s0, s1); | |
| 280 | 40 | s0 = _mm_packus_epi16(s0, s0); | |
| 281 | 40 | _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + x), s0); | |
| 282 | } | ||
| 283 | 10 | srcp += src_pitch; | |
| 284 | 10 | dstp += dst_pitch; | |
| 285 | } | ||
| 286 | 2 | } | |
| 287 | |||
| 288 | template <bool has_clipY> | ||
| 289 | 2 | void yuy2_ytouv_sse2(const BYTE* srcp_y, const BYTE* srcp_u, const BYTE* srcp_v, BYTE* dstp, int pitch_y, int pitch_u, int pitch_v, int dst_pitch, int dst_rowsize, int height) | |
| 290 | { | ||
| 291 | 2 | const __m128i mask = _mm_set1_epi16(0x00FF); | |
| 292 | 2 | const __m128i zero = _mm_setzero_si128(); | |
| 293 | 2 | const __m128i fill = _mm_set1_epi16(0x007e); | |
| 294 | |||
| 295 |
4/4void yuy2_ytouv_sse2<false>(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, int, int, int, int, int, int):
✓ Branch 38 → 13 taken 5 times.
✓ Branch 38 → 39 taken 1 time.
void yuy2_ytouv_sse2<true>(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, int, int, int, int, int, int):
✓ Branch 47 → 13 taken 5 times.
✓ Branch 47 → 48 taken 1 time.
|
12 | for (int y = 0; y < height; ++y) { |
| 296 |
4/4void yuy2_ytouv_sse2<false>(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, int, int, int, int, int, int):
✓ Branch 36 → 14 taken 10 times.
✓ Branch 36 → 37 taken 5 times.
void yuy2_ytouv_sse2<true>(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, int, int, int, int, int, int):
✓ Branch 45 → 14 taken 10 times.
✓ Branch 45 → 46 taken 5 times.
|
30 | for (int x = 0; x < dst_rowsize; x += 32) { |
| 297 | 20 | __m128i u = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp_u + x / 2)); | |
| 298 | 40 | __m128i v = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp_v + x / 2)); | |
| 299 | 60 | __m128i uv = _mm_or_si128(_mm_and_si128(u, mask), _mm_slli_epi16(v, 8)); | |
| 300 | 20 | __m128i uv_lo = _mm_unpacklo_epi8(zero, uv); | |
| 301 | 20 | __m128i uv_hi = _mm_unpackhi_epi8(zero, uv); | |
| 302 | if (has_clipY) { | ||
| 303 | 10 | __m128i y_lo = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp_y + x)); | |
| 304 | 20 | __m128i y_hi = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp_y + x + 16)); | |
| 305 | 20 | uv_lo = _mm_or_si128(uv_lo, _mm_and_si128(y_lo, mask)); | |
| 306 | 20 | uv_hi = _mm_or_si128(uv_hi, _mm_and_si128(y_hi, mask)); | |
| 307 | } | ||
| 308 | else { | ||
| 309 | 10 | uv_lo = _mm_or_si128(uv_lo, fill); | |
| 310 | 10 | uv_hi = _mm_or_si128(uv_hi, fill); | |
| 311 | } | ||
| 312 | 20 | _mm_stream_si128(reinterpret_cast<__m128i*>(dstp + x), uv_lo); | |
| 313 | 20 | _mm_stream_si128(reinterpret_cast<__m128i*>(dstp + x + 16), uv_hi); | |
| 314 | } | ||
| 315 | 10 | srcp_y += pitch_y; | |
| 316 | 10 | srcp_u += pitch_u; | |
| 317 | 10 | srcp_v += pitch_v; | |
| 318 | 10 | dstp += dst_pitch; | |
| 319 | } | ||
| 320 | 2 | } | |
| 321 | |||
| 322 | template void yuy2_ytouv_sse2<false>(const BYTE* srcp_y, const BYTE* srcp_u, const BYTE* srcp_v, BYTE* dstp, int pitch_y, int pitch_u, int pitch_v, int dst_pitch, int dst_rowsize, int height); | ||
| 323 | template void yuy2_ytouv_sse2<true>(const BYTE* srcp_y, const BYTE* srcp_u, const BYTE* srcp_v, BYTE* dstp, int pitch_y, int pitch_u, int pitch_v, int dst_pitch, int dst_rowsize, int height); | ||
| 324 |