1/* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/modules/desktop_capture/differ_block_sse2.h" 12 13#if defined(_MSC_VER) 14#include <intrin.h> 15#else 16#include <mmintrin.h> 17#include <emmintrin.h> 18#endif 19 20#include "webrtc/modules/desktop_capture/differ_block.h" 21 22namespace webrtc { 23 24extern bool BlockDifference_SSE2_W16(const uint8_t* image1, 25 const uint8_t* image2, 26 int stride) { 27 __m128i acc = _mm_setzero_si128(); 28 __m128i v0; 29 __m128i v1; 30 __m128i sad; 31 for (int y = 0; y < kBlockSize; ++y) { 32 const __m128i* i1 = reinterpret_cast<const __m128i*>(image1); 33 const __m128i* i2 = reinterpret_cast<const __m128i*>(image2); 34 v0 = _mm_loadu_si128(i1); 35 v1 = _mm_loadu_si128(i2); 36 sad = _mm_sad_epu8(v0, v1); 37 acc = _mm_adds_epu16(acc, sad); 38 v0 = _mm_loadu_si128(i1 + 1); 39 v1 = _mm_loadu_si128(i2 + 1); 40 sad = _mm_sad_epu8(v0, v1); 41 acc = _mm_adds_epu16(acc, sad); 42 v0 = _mm_loadu_si128(i1 + 2); 43 v1 = _mm_loadu_si128(i2 + 2); 44 sad = _mm_sad_epu8(v0, v1); 45 acc = _mm_adds_epu16(acc, sad); 46 v0 = _mm_loadu_si128(i1 + 3); 47 v1 = _mm_loadu_si128(i2 + 3); 48 sad = _mm_sad_epu8(v0, v1); 49 acc = _mm_adds_epu16(acc, sad); 50 51 // This essential means sad = acc >> 64. We only care about the lower 16 52 // bits. 53 sad = _mm_shuffle_epi32(acc, 0xEE); 54 sad = _mm_adds_epu16(sad, acc); 55 int diff = _mm_cvtsi128_si32(sad); 56 if (diff) 57 return true; 58 image1 += stride; 59 image2 += stride; 60 } 61 return false; 62} 63 64extern bool BlockDifference_SSE2_W32(const uint8_t* image1, 65 const uint8_t* image2, 66 int stride) { 67 __m128i acc = _mm_setzero_si128(); 68 __m128i v0; 69 __m128i v1; 70 __m128i sad; 71 for (int y = 0; y < kBlockSize; ++y) { 72 const __m128i* i1 = reinterpret_cast<const __m128i*>(image1); 73 const __m128i* i2 = reinterpret_cast<const __m128i*>(image2); 74 v0 = _mm_loadu_si128(i1); 75 v1 = _mm_loadu_si128(i2); 76 sad = _mm_sad_epu8(v0, v1); 77 acc = _mm_adds_epu16(acc, sad); 78 v0 = _mm_loadu_si128(i1 + 1); 79 v1 = _mm_loadu_si128(i2 + 1); 80 sad = _mm_sad_epu8(v0, v1); 81 acc = _mm_adds_epu16(acc, sad); 82 v0 = _mm_loadu_si128(i1 + 2); 83 v1 = _mm_loadu_si128(i2 + 2); 84 sad = _mm_sad_epu8(v0, v1); 85 acc = _mm_adds_epu16(acc, sad); 86 v0 = _mm_loadu_si128(i1 + 3); 87 v1 = _mm_loadu_si128(i2 + 3); 88 sad = _mm_sad_epu8(v0, v1); 89 acc = _mm_adds_epu16(acc, sad); 90 v0 = _mm_loadu_si128(i1 + 4); 91 v1 = _mm_loadu_si128(i2 + 4); 92 sad = _mm_sad_epu8(v0, v1); 93 acc = _mm_adds_epu16(acc, sad); 94 v0 = _mm_loadu_si128(i1 + 5); 95 v1 = _mm_loadu_si128(i2 + 5); 96 sad = _mm_sad_epu8(v0, v1); 97 acc = _mm_adds_epu16(acc, sad); 98 v0 = _mm_loadu_si128(i1 + 6); 99 v1 = _mm_loadu_si128(i2 + 6); 100 sad = _mm_sad_epu8(v0, v1); 101 acc = _mm_adds_epu16(acc, sad); 102 v0 = _mm_loadu_si128(i1 + 7); 103 v1 = _mm_loadu_si128(i2 + 7); 104 sad = _mm_sad_epu8(v0, v1); 105 acc = _mm_adds_epu16(acc, sad); 106 107 // This essential means sad = acc >> 64. We only care about the lower 16 108 // bits. 109 sad = _mm_shuffle_epi32(acc, 0xEE); 110 sad = _mm_adds_epu16(sad, acc); 111 int diff = _mm_cvtsi128_si32(sad); 112 if (diff) 113 return true; 114 image1 += stride; 115 image2 += stride; 116 } 117 return false; 118} 119 120} // namespace webrtc 121