filters/intel/text-overlay_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 | #include <avisynth.h> | ||
| 36 | #include <avs/minmax.h> | ||
| 37 | #define __STDC_FORMAT_MACROS | ||
| 38 | #include <inttypes.h> | ||
| 39 | |||
| 40 | // Intrinsics base header + really required extension headers | ||
| 41 | #if defined(_MSC_VER) | ||
| 42 | #include <intrin.h> // MSVC | ||
| 43 | #else | ||
| 44 | #include <x86intrin.h> // GCC/MinGW/Clang/LLVM | ||
| 45 | #endif | ||
| 46 | |||
| 47 | |||
| 48 | 8 | void compare_sse2(uint32_t mask, int increment, | |
| 49 | const BYTE * f1ptr, int pitch1, | ||
| 50 | const BYTE * f2ptr, int pitch2, | ||
| 51 | int rowsize, int height, | ||
| 52 | int &SAD_sum, int &SD_sum, int &pos_D, int &neg_D, double &SSD_sum) | ||
| 53 | { | ||
| 54 | // rowsize multiple of 16 for YUV Planar, RGB32 and YUY2; 12 for RGB24 | ||
| 55 | // increment must be 3 for RGB24 and 4 for others | ||
| 56 | |||
| 57 | 8 | int64_t issd = 0; | |
| 58 | 8 | __m128i sad_vector = _mm_setzero_si128(); //sum of absolute differences | |
| 59 | 8 | __m128i sd_vector = _mm_setzero_si128(); // sum of differences | |
| 60 | 8 | __m128i positive_diff = _mm_setzero_si128(); | |
| 61 | 8 | __m128i negative_diff = _mm_setzero_si128(); | |
| 62 | 8 | __m128i zero = _mm_setzero_si128(); | |
| 63 | |||
| 64 | 8 | __m128i mask64 = _mm_set_epi32(0, 0, 0, mask); | |
| 65 |
2/2✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 20 taken 6 times.
|
8 | if (increment == 3) { |
| 66 | 2 | mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 3)); | |
| 67 | 4 | mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 6)); | |
| 68 | } else { | ||
| 69 | 6 | mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 4)); | |
| 70 | 12 | mask64 = _mm_or_si128(mask64, _mm_slli_si128(mask64, 8)); | |
| 71 | } | ||
| 72 | |||
| 73 | |||
| 74 | |||
| 75 |
2/2✓ Branch 80 → 26 taken 2194 times.
✓ Branch 80 → 81 taken 8 times.
|
2202 | for (int y = 0; y < height; ++y) { |
| 76 | 2194 | __m128i row_ssd = _mm_setzero_si128(); // sum of squared differences (row_SSD) | |
| 77 | |||
| 78 |
2/2✓ Branch 72 → 29 taken 2073717 times.
✓ Branch 72 → 73 taken 2194 times.
|
2075911 | for (int x = 0; x < rowsize; x+=increment*4) { |
| 79 | 2073717 | __m128i src1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(f1ptr+x)); | |
| 80 | 4147434 | __m128i src2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(f2ptr+x)); | |
| 81 | |||
| 82 | 2073717 | src1 = _mm_and_si128(src1, mask64); | |
| 83 | 2073717 | src2 = _mm_and_si128(src2, mask64); | |
| 84 | |||
| 85 | 2073717 | __m128i diff_1_minus_2 = _mm_subs_epu8(src1, src2); | |
| 86 | 2073717 | __m128i diff_2_minus_1 = _mm_subs_epu8(src2, src1); | |
| 87 | |||
| 88 | 2073717 | positive_diff = _mm_max_epu8(positive_diff, diff_1_minus_2); | |
| 89 | 2073717 | negative_diff = _mm_max_epu8(negative_diff, diff_2_minus_1); | |
| 90 | |||
| 91 | 2073717 | __m128i absdiff1 = _mm_sad_epu8(diff_1_minus_2, zero); | |
| 92 | 2073717 | __m128i absdiff2 = _mm_sad_epu8(diff_2_minus_1, zero); | |
| 93 | |||
| 94 | 2073717 | sad_vector = _mm_add_epi32(sad_vector, absdiff1); | |
| 95 | 2073717 | sad_vector = _mm_add_epi32(sad_vector, absdiff2); | |
| 96 | |||
| 97 | 2073717 | sd_vector = _mm_add_epi32(sd_vector, absdiff1); | |
| 98 | 2073717 | sd_vector = _mm_sub_epi32(sd_vector, absdiff2); | |
| 99 | |||
| 100 | 2073717 | __m128i ssd = _mm_or_si128(diff_1_minus_2, diff_2_minus_1); | |
| 101 | 2073717 | __m128i ssd_lo = _mm_unpacklo_epi8(ssd, zero); | |
| 102 | 2073717 | __m128i ssd_hi = _mm_unpackhi_epi8(ssd, zero); | |
| 103 | 2073717 | ssd_lo = _mm_madd_epi16(ssd_lo, ssd_lo); | |
| 104 | 2073717 | ssd_hi = _mm_madd_epi16(ssd_hi, ssd_hi); | |
| 105 | 2073717 | row_ssd = _mm_add_epi32(row_ssd, ssd_lo); | |
| 106 | 2073717 | row_ssd = _mm_add_epi32(row_ssd, ssd_hi); | |
| 107 | } | ||
| 108 | |||
| 109 | 2194 | f1ptr += pitch1; | |
| 110 | 2194 | f2ptr += pitch2; | |
| 111 | |||
| 112 | 2194 | __m128i tmp = _mm_srli_si128(row_ssd, 8); | |
| 113 | 2194 | row_ssd = _mm_add_epi32(row_ssd, tmp); | |
| 114 | 2194 | tmp = _mm_srli_si128(row_ssd, 4); | |
| 115 | 2194 | row_ssd = _mm_add_epi32(row_ssd, tmp); | |
| 116 | |||
| 117 | 2194 | issd += _mm_cvtsi128_si32(row_ssd); | |
| 118 | } | ||
| 119 | |||
| 120 | 8 | SAD_sum += _mm_cvtsi128_si32(sad_vector); | |
| 121 | 16 | SAD_sum += _mm_cvtsi128_si32(_mm_srli_si128(sad_vector, 8)); | |
| 122 | 8 | SD_sum += _mm_cvtsi128_si32(sd_vector); | |
| 123 | 16 | SD_sum += _mm_cvtsi128_si32(_mm_srli_si128(sd_vector, 8)); | |
| 124 | |||
| 125 | BYTE posdiff_tmp[16]; | ||
| 126 | BYTE negdiff_tmp[16]; | ||
| 127 | _mm_store_si128(reinterpret_cast<__m128i*>(posdiff_tmp), positive_diff); | ||
| 128 | _mm_store_si128(reinterpret_cast<__m128i*>(negdiff_tmp), negative_diff); | ||
| 129 | |||
| 130 | 8 | SSD_sum += (double)issd; | |
| 131 | |||
| 132 | 8 | neg_D = -neg_D; // 160801! false neg_D fix for isse | |
| 133 | |||
| 134 |
2/2✓ Branch 95 → 92 taken 120 times.
✓ Branch 95 → 96 taken 8 times.
|
128 | for (int i = 0; i < increment*4; ++i) { |
| 135 | 120 | pos_D = max(pos_D, (int)(posdiff_tmp[i])); | |
| 136 | 120 | neg_D = max(neg_D, (int)(negdiff_tmp[i])); | |
| 137 | } | ||
| 138 | |||
| 139 | 8 | neg_D = -neg_D; | |
| 140 | 8 | } | |
| 141 | |||
| 142 | #ifdef X86_32 | ||
| 143 | |||
| 144 | void compare_isse(uint32_t mask, int increment, | ||
| 145 | const BYTE * f1ptr, int pitch1, | ||
| 146 | const BYTE * f2ptr, int pitch2, | ||
| 147 | int rowsize, int height, | ||
| 148 | int &SAD_sum, int &SD_sum, int &pos_D, int &neg_D, double &SSD_sum) | ||
| 149 | { | ||
| 150 | // rowsize multiple of 8 for YUV Planar, RGB32 and YUY2; 6 for RGB24 | ||
| 151 | // increment must be 3 for RGB24 and 4 for others | ||
| 152 | |||
| 153 | int64_t issd = 0; | ||
| 154 | __m64 sad_vector = _mm_setzero_si64(); //sum of absolute differences | ||
| 155 | __m64 sd_vector = _mm_setzero_si64(); // sum of differences | ||
| 156 | __m64 positive_diff = _mm_setzero_si64(); | ||
| 157 | __m64 negative_diff = _mm_setzero_si64(); | ||
| 158 | __m64 zero = _mm_setzero_si64(); | ||
| 159 | |||
| 160 | __m64 mask64 = _mm_set_pi32(0, mask); | ||
| 161 | mask64 = _mm_or_si64(mask64, _mm_slli_si64(mask64, increment*8)); | ||
| 162 | |||
| 163 | |||
| 164 | for (int y = 0; y < height; ++y) { | ||
| 165 | __m64 row_ssd = _mm_setzero_si64(); // sum of squared differences (row_SSD) | ||
| 166 | |||
| 167 | for (int x = 0; x < rowsize; x+=increment*2) { | ||
| 168 | __m64 src1 = *reinterpret_cast<const __m64*>(f1ptr+x); | ||
| 169 | __m64 src2 = *reinterpret_cast<const __m64*>(f2ptr+x); | ||
| 170 | |||
| 171 | src1 = _mm_and_si64(src1, mask64); | ||
| 172 | src2 = _mm_and_si64(src2, mask64); | ||
| 173 | |||
| 174 | __m64 diff_1_minus_2 = _mm_subs_pu8(src1, src2); | ||
| 175 | __m64 diff_2_minus_1 = _mm_subs_pu8(src2, src1); | ||
| 176 | |||
| 177 | positive_diff = _mm_max_pu8(positive_diff, diff_1_minus_2); | ||
| 178 | negative_diff = _mm_max_pu8(negative_diff, diff_2_minus_1); | ||
| 179 | |||
| 180 | __m64 absdiff1 = _mm_sad_pu8(diff_1_minus_2, zero); | ||
| 181 | __m64 absdiff2 = _mm_sad_pu8(diff_2_minus_1, zero); | ||
| 182 | |||
| 183 | sad_vector = _mm_add_pi32(sad_vector, absdiff1); | ||
| 184 | sad_vector = _mm_add_pi32(sad_vector, absdiff2); | ||
| 185 | |||
| 186 | sd_vector = _mm_add_pi32(sd_vector, absdiff1); | ||
| 187 | sd_vector = _mm_sub_pi32(sd_vector, absdiff2); | ||
| 188 | |||
| 189 | __m64 ssd = _mm_or_si64(diff_1_minus_2, diff_2_minus_1); | ||
| 190 | __m64 ssd_lo = _mm_unpacklo_pi8(ssd, zero); | ||
| 191 | __m64 ssd_hi = _mm_unpackhi_pi8(ssd, zero); | ||
| 192 | ssd_lo = _mm_madd_pi16(ssd_lo, ssd_lo); | ||
| 193 | ssd_hi = _mm_madd_pi16(ssd_hi, ssd_hi); | ||
| 194 | row_ssd = _mm_add_pi32(row_ssd, ssd_lo); | ||
| 195 | row_ssd = _mm_add_pi32(row_ssd, ssd_hi); | ||
| 196 | } | ||
| 197 | |||
| 198 | f1ptr += pitch1; | ||
| 199 | f2ptr += pitch2; | ||
| 200 | |||
| 201 | __m64 tmp = _mm_unpackhi_pi32(row_ssd, zero); | ||
| 202 | row_ssd = _mm_add_pi32(row_ssd, tmp); | ||
| 203 | |||
| 204 | issd += _mm_cvtsi64_si32(row_ssd); | ||
| 205 | } | ||
| 206 | |||
| 207 | SAD_sum += _mm_cvtsi64_si32(sad_vector); | ||
| 208 | SD_sum += _mm_cvtsi64_si32(sd_vector); | ||
| 209 | |||
| 210 | BYTE posdiff_tmp[8]; | ||
| 211 | BYTE negdiff_tmp[8]; | ||
| 212 | *reinterpret_cast<__m64*>(posdiff_tmp) = positive_diff; | ||
| 213 | *reinterpret_cast<__m64*>(negdiff_tmp) = negative_diff; | ||
| 214 | _mm_empty(); | ||
| 215 | |||
| 216 | SSD_sum += (double)issd; | ||
| 217 | |||
| 218 | neg_D = -neg_D; // 160801! false neg_D fix for isse | ||
| 219 | |||
| 220 | for (int i = 0; i < increment*2; ++i) { | ||
| 221 | pos_D = max(pos_D, (int)(posdiff_tmp[i])); | ||
| 222 | neg_D = max(neg_D, (int)(negdiff_tmp[i])); | ||
| 223 | } | ||
| 224 | |||
| 225 | neg_D = -neg_D; | ||
| 226 | } | ||
| 227 | |||
| 228 | #endif | ||
| 229 | |||
| 230 | |||
| 231 | |||
| 232 |