11 #include <emmintrin.h>
23 [[nodiscard]]
const void* getLineInfo(
24 unsigned line,
unsigned& width,
25 void* buf,
unsigned bufWidth)
const override;
34 std::unique_ptr<RawFrame>* lastFrames)
37 if (
format.getBytesPerPixel() == 2) {
42 if (
format.getBytesPerPixel() == 4) {
51 std::unique_ptr<RawFrame>* lastFrames_)
53 , lastFrames(lastFrames_)
65 return lastFrames[0]->getLineWidthDirect(line);
69 template<
typename Pixel>
71 std::unique_ptr<RawFrame>* lastFrames_)
78 template<
typename Pixel>
79 static __m128i blend(__m128i
x, __m128i y,
Pixel blendMask)
81 if (
sizeof(
Pixel) == 4) {
83 return _mm_avg_epu8(
x, y);
86 __m128i m = _mm_set1_epi16(blendMask);
87 __m128i a = _mm_and_si128(
x, y);
88 __m128i b = _mm_xor_si128(
x, y);
89 __m128i c = _mm_and_si128(b, m);
90 __m128i d = _mm_srli_epi16(c, 1);
91 return _mm_add_epi16(a, d);
95 template<
typename Pixel>
96 static __m128i uload(
const Pixel* ptr, ptrdiff_t byteOffst)
98 const auto* p8 =
reinterpret_cast<const char *
>(ptr);
99 const auto* p128 =
reinterpret_cast<const __m128i*
>(p8 + byteOffst);
100 return _mm_loadu_si128(p128);
103 template<
typename Pixel>
104 static void ustore(
Pixel* ptr, ptrdiff_t byteOffst, __m128i val)
106 auto* p8 =
reinterpret_cast< char *
>(ptr);
107 auto* p128 =
reinterpret_cast<__m128i*
>(p8 + byteOffst);
108 return _mm_storeu_si128(p128, val);
111 template<
typename Pixel>
112 static __m128i compare(__m128i
x, __m128i y)
115 if (
sizeof(
Pixel) == 4) {
116 return _mm_cmpeq_epi32(
x, y);
118 return _mm_cmpeq_epi16(
x, y);
123 template<
typename Pixel>
124 const void* DeflickerImpl<Pixel>::getLineInfo(
125 unsigned line,
unsigned& width,
void* buf_,
unsigned bufWidth)
const
127 unsigned width0 = lastFrames[0]->getLineWidthDirect(line);
128 unsigned width1 = lastFrames[1]->getLineWidthDirect(line);
129 unsigned width2 = lastFrames[2]->getLineWidthDirect(line);
130 unsigned width3 = lastFrames[3]->getLineWidthDirect(line);
131 const Pixel* line0 = lastFrames[0]->template getLinePtrDirect<Pixel>(line);
132 const Pixel* line1 = lastFrames[1]->template getLinePtrDirect<Pixel>(line);
133 const Pixel* line2 = lastFrames[2]->template getLinePtrDirect<Pixel>(line);
134 const Pixel* line3 = lastFrames[3]->template getLinePtrDirect<Pixel>(line);
135 if ((width0 != width3) || (width0 != width2) || (width0 != width1)) {
144 auto* buf =
static_cast<Pixel*
>(buf_);
145 Pixel* out = (width0 <= bufWidth) ? buf : buf2;
153 unsigned remaining = width0;
155 size_t pixelsPerSSE =
sizeof(__m128i) /
sizeof(
Pixel);
156 size_t widthSSE = remaining & ~(pixelsPerSSE - 1);
162 auto byteOffst = -ptrdiff_t(widthSSE *
sizeof(
Pixel));
164 Pixel blendMask = pixelOps.getBlendMask();
165 while (byteOffst < 0) {
166 __m128i a0 = uload(line0, byteOffst);
167 __m128i a1 = uload(line1, byteOffst);
168 __m128i a2 = uload(line2, byteOffst);
169 __m128i a3 = uload(line3, byteOffst);
171 __m128i e02 = compare<Pixel>(a0, a2);
172 __m128i e13 = compare<Pixel>(a1, a3);
173 __m128i cnd = _mm_and_si128(e02, e13);
175 __m128i a01 = blend(a0, a1, blendMask);
176 __m128i p = _mm_xor_si128(a0, a01);
177 __m128i q = _mm_and_si128(p, cnd);
178 __m128i r = _mm_xor_si128(q, a0);
180 ustore(dst, byteOffst, r);
181 byteOffst +=
sizeof(__m128i);
183 remaining &= pixelsPerSSE - 1;
185 for (
auto x :
xrange(remaining)) {
186 dst[
x] = ((line0[
x] == line2[
x]) && (line1[
x] == line3[
x]))
187 ? pixelOps.template blend<1, 1>(line0[
x], line1[
x])
191 if (width0 <= bufWidth) {
197 scaleLine(out, buf, width0, bufWidth);
DeflickerImpl(const PixelFormat &format, std::unique_ptr< RawFrame > *lastFrames)
static std::unique_ptr< Deflicker > create(const PixelFormat &format, std::unique_ptr< RawFrame > *lastFrames)
std::unique_ptr< RawFrame > * lastFrames
Deflicker(const PixelFormat &format, std::unique_ptr< RawFrame > *lastFrames)
unsigned getLineWidth(unsigned line) const override
Gets the number of display pixels on the given line.
Interface for getting lines from a video frame.
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.
void format(SectorAccessibleDisk &disk, bool dos1)
Format the given disk (= a single partition).
This file implemented 3 utility functions:
constexpr KeyMatrixPosition x
Keyboard bindings.
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
constexpr auto xrange(T e)