21 std::span<std::unique_ptr<RawFrame>, 4>
lastFrames);
24 [[nodiscard]]
const void* getLineInfo(
25 unsigned line,
unsigned& width,
26 void* buf,
unsigned bufWidth)
const override;
35 std::span<std::unique_ptr<RawFrame>, 4> lastFrames)
38 if (
format.getBytesPerPixel() == 2) {
43 if (
format.getBytesPerPixel() == 4) {
52 std::span<std::unique_ptr<RawFrame>, 4> lastFrames_)
54 , lastFrames(lastFrames_)
66 return lastFrames[0]->getLineWidthDirect(line);
70template<std::
unsigned_
integral Pixel>
72 std::span<std::unique_ptr<RawFrame>, 4> lastFrames_)
79template<std::
unsigned_
integral Pixel>
80static __m128i blend(__m128i x, __m128i y,
Pixel blendMask)
82 if constexpr (
sizeof(
Pixel) == 4) {
84 return _mm_avg_epu8(x, y);
87 __m128i m = _mm_set1_epi16(blendMask);
88 __m128i a = _mm_and_si128(x, y);
89 __m128i b = _mm_xor_si128(x, y);
90 __m128i c = _mm_and_si128(b, m);
91 __m128i d = _mm_srli_epi16(c, 1);
92 return _mm_add_epi16(a, d);
96template<std::
unsigned_
integral Pixel>
97static __m128i uload(
const Pixel* ptr, ptrdiff_t byteOffst)
99 const auto* p8 =
reinterpret_cast<const char *
>(ptr);
100 const auto* p128 =
reinterpret_cast<const __m128i*
>(p8 + byteOffst);
101 return _mm_loadu_si128(p128);
104template<std::
unsigned_
integral Pixel>
105static void ustore(
Pixel* ptr, ptrdiff_t byteOffst, __m128i val)
107 auto* p8 =
reinterpret_cast< char *
>(ptr);
108 auto* p128 =
reinterpret_cast<__m128i*
>(p8 + byteOffst);
109 return _mm_storeu_si128(p128, val);
112template<std::
unsigned_
integral Pixel>
113static __m128i compare(__m128i x, __m128i y)
116 if constexpr (
sizeof(
Pixel) == 4) {
117 return _mm_cmpeq_epi32(x, y);
119 return _mm_cmpeq_epi16(x, y);
124template<std::
unsigned_
integral Pixel>
125const void* DeflickerImpl<Pixel>::getLineInfo(
126 unsigned line,
unsigned& width,
void* buf_,
unsigned bufWidth)
const
128 unsigned width0 = lastFrames[0]->getLineWidthDirect(line);
129 unsigned width1 = lastFrames[1]->getLineWidthDirect(line);
130 unsigned width2 = lastFrames[2]->getLineWidthDirect(line);
131 unsigned width3 = lastFrames[3]->getLineWidthDirect(line);
132 const Pixel* line0 = lastFrames[0]->template getLineDirect<Pixel>(line).data();
133 const Pixel* line1 = lastFrames[1]->template getLineDirect<Pixel>(line).data();
134 const Pixel* line2 = lastFrames[2]->template getLineDirect<Pixel>(line).data();
135 const Pixel* line3 = lastFrames[3]->template getLineDirect<Pixel>(line).data();
136 if ((width0 != width3) || (width0 != width2) || (width0 != width1)) {
145 auto* buf =
static_cast<Pixel*
>(buf_);
146 Pixel* out = (width0 <= bufWidth) ? buf : buf2.data();
154 size_t remaining = width0;
156 size_t pixelsPerSSE =
sizeof(__m128i) /
sizeof(
Pixel);
157 size_t widthSSE = remaining & ~(pixelsPerSSE - 1);
163 auto byteOffst = -ptrdiff_t(widthSSE *
sizeof(
Pixel));
165 Pixel blendMask = pixelOps.getBlendMask();
166 while (byteOffst < 0) {
167 __m128i a0 = uload(line0, byteOffst);
168 __m128i a1 = uload(line1, byteOffst);
169 __m128i a2 = uload(line2, byteOffst);
170 __m128i a3 = uload(line3, byteOffst);
172 __m128i e02 = compare<Pixel>(a0, a2);
173 __m128i e13 = compare<Pixel>(a1, a3);
174 __m128i cnd = _mm_and_si128(e02, e13);
176 __m128i a01 = blend(a0, a1, blendMask);
177 __m128i p = _mm_xor_si128(a0, a01);
178 __m128i q = _mm_and_si128(p, cnd);
179 __m128i r = _mm_xor_si128(q, a0);
181 ustore(dst, byteOffst, r);
182 byteOffst +=
sizeof(__m128i);
184 remaining &= pixelsPerSSE - 1;
186 for (
auto x :
xrange(remaining)) {
187 dst[x] = ((line0[x] == line2[x]) && (line1[x] == line3[x]))
188 ? pixelOps.template blend<1, 1>(line0[x], line1[x])
192 if (width0 <= bufWidth) {
198 scaleLine(std::span<const Pixel>{out, width0}, std::span{buf, bufWidth});
DeflickerImpl(const PixelFormat &format, std::span< std::unique_ptr< RawFrame >, 4 > lastFrames)
std::span< std::unique_ptr< RawFrame >, 4 > lastFrames
static std::unique_ptr< Deflicker > create(const PixelFormat &format, std::span< std::unique_ptr< RawFrame >, 4 > lastFrames)
Deflicker(const PixelFormat &format, std::span< std::unique_ptr< RawFrame >, 4 > 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, MSXBootSectorType bootType)
Format the given disk (= a single partition).
This file implemented 3 utility functions:
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
constexpr auto xrange(T e)