12using Pixel = uint32_t;
15 : lastFrames(lastFrames_)
27 return lastFrames[0]->getLineWidthDirect(line);
31static __m128i blend(__m128i x, __m128i y)
34 return _mm_avg_epu8(x, y);
37static __m128i uload(
const Pixel* ptr, ptrdiff_t byteOffst)
39 const auto* p8 =
reinterpret_cast<const char *
>(ptr);
40 const auto* p128 =
reinterpret_cast<const __m128i*
>(p8 + byteOffst);
41 return _mm_loadu_si128(p128);
44static void ustore(
Pixel* ptr, ptrdiff_t byteOffst, __m128i val)
46 auto* p8 =
reinterpret_cast< char *
>(ptr);
47 auto* p128 =
reinterpret_cast<__m128i*
>(p8 + byteOffst);
48 return _mm_storeu_si128(p128, val);
51static __m128i compare(__m128i x, __m128i y)
54 return _mm_cmpeq_epi32(x, y);
59 unsigned line,
unsigned& width,
void* buf_,
unsigned bufWidth)
const
61 unsigned width0 = lastFrames[0]->getLineWidthDirect(line);
62 unsigned width1 = lastFrames[1]->getLineWidthDirect(line);
63 unsigned width2 = lastFrames[2]->getLineWidthDirect(line);
64 unsigned width3 = lastFrames[3]->getLineWidthDirect(line);
65 const Pixel* line0 = lastFrames[0]->getLineDirect(line).data();
66 const Pixel* line1 = lastFrames[1]->getLineDirect(line).data();
67 const Pixel* line2 = lastFrames[2]->getLineDirect(line).data();
68 const Pixel* line3 = lastFrames[3]->getLineDirect(line).data();
69 if ((width0 != width3) || (width0 != width2) || (width0 != width1)) {
78 auto* buf =
static_cast<Pixel*
>(buf_);
79 Pixel* out = (width0 <= bufWidth) ? buf : buf2.data();
87 size_t remaining = width0;
89 size_t pixelsPerSSE =
sizeof(__m128i) /
sizeof(
Pixel);
90 size_t widthSSE = remaining & ~(pixelsPerSSE - 1);
96 auto byteOffst = -ptrdiff_t(widthSSE *
sizeof(
Pixel));
98 while (byteOffst < 0) {
99 __m128i a0 = uload(line0, byteOffst);
100 __m128i a1 = uload(line1, byteOffst);
101 __m128i a2 = uload(line2, byteOffst);
102 __m128i a3 = uload(line3, byteOffst);
104 __m128i e02 = compare(a0, a2);
105 __m128i e13 = compare(a1, a3);
106 __m128i cnd = _mm_and_si128(e02, e13);
108 __m128i a01 = blend(a0, a1);
109 __m128i p = _mm_xor_si128(a0, a01);
110 __m128i q = _mm_and_si128(p, cnd);
111 __m128i r = _mm_xor_si128(q, a0);
113 ustore(dst, byteOffst, r);
114 byteOffst +=
sizeof(__m128i);
116 remaining &= pixelsPerSSE - 1;
119 for (
auto x :
xrange(remaining)) {
120 dst[x] = ((line0[x] == line2[x]) && (line1[x] == line3[x]))
121 ? pixelOps.template blend<1, 1>(line0[x], line1[x])
125 if (width0 <= bufWidth) {
131 scaleLine(std::span<const Pixel>{out, width0}, std::span{buf, bufWidth});
const void * getLineInfo(unsigned line, unsigned &width, void *buf, unsigned bufWidth) const override
Abstract implementation of getLinePtr().
Deflicker(std::span< std::unique_ptr< RawFrame >, 4 > lastFrames)
unsigned getLineWidth(unsigned line) const override
Gets the number of display pixels on the given line.
void scaleLine(std::span< const Pixel > in, std::span< Pixel > out) const
void setHeight(unsigned height_)
void init(FieldType fieldType_)
(Re)initialize an existing FrameSource.
unsigned getHeight() const
Gets the number of lines in this frame.
@ FIELD_NONINTERLACED
Interlacing is off for this frame.
This file implemented 3 utility functions:
CharacterConverter::Pixel Pixel
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
constexpr auto xrange(T e)