14 template<
typename Pixel>
21 , settings(renderSettings)
25 template<
typename Pixel>
28 unsigned c1 = settings.getBlurFactor();
29 unsigned c2 = (3 * 256) - (2 * c1);
33 [[nodiscard]]
static inline std::pair<unsigned, unsigned> calcSpill(
unsigned c1,
unsigned c2,
unsigned x)
35 unsigned r = (c2 *
x) >> 8;
36 unsigned s = (c1 *
x) >> 8;
44 template<
typename Pixel>
45 void RGBTriplet3xScaler<Pixel>::rgbify(
46 const Pixel* __restrict in,
Pixel* __restrict out,
unsigned inWidth,
47 unsigned c1,
unsigned c2)
51 auto [r, rs] = calcSpill(c1, c2, pixelOps.red256 (in[i + 0]));
52 auto [
g, gs] = calcSpill(c1, c2, pixelOps.green256(in[i + 0]));
53 out[3 * i + 0] = pixelOps.combine256(r , gs, 0);
54 auto [b, bs] = calcSpill(c1, c2, pixelOps.blue256 (in[i + 0]));
55 out[3 * i + 1] = pixelOps.combine256(rs,
g , bs);
56 std::tie(r, rs) = calcSpill(c1, c2, pixelOps.red256 (in[i + 1]));
57 out[3 * i + 2] = pixelOps.combine256(rs, gs, b);
59 for (++i; i < (inWidth - 1); ++i) {
60 std::tie(
g, gs) = calcSpill(c1, c2, pixelOps.green256(in[i + 0]));
61 out[3 * i + 0] = pixelOps.combine256(r , gs, bs);
62 std::tie(b, bs) = calcSpill(c1, c2, pixelOps.blue256 (in[i + 0]));
63 out[3 * i + 1] = pixelOps.combine256(rs,
g , bs);
64 std::tie(r, rs) = calcSpill(c1, c2, pixelOps.red256 (in[i + 1]));
65 out[3 * i + 2] = pixelOps.combine256(rs, gs, b);
68 std::tie(
g, gs) = calcSpill(c1, c2, pixelOps.green256(in[i + 0]));
69 out[3 * i + 0] = pixelOps.combine256(r , gs, bs);
70 std::tie(b, bs) = calcSpill(c1, c2, pixelOps.blue256 (in[i + 0]));
71 out[3 * i + 1] = pixelOps.combine256(rs,
g , bs);
72 out[3 * i + 2] = pixelOps.combine256(0 , gs, b);
75 template<
typename Pixel>
76 void RGBTriplet3xScaler<Pixel>::scaleLine(
78 unsigned tmpWidth,
unsigned c1,
unsigned c2)
81 rgbify(srcLine, dstLine, tmpWidth, c1, c2);
84 scale(srcLine, tmp, tmpWidth);
85 rgbify(tmp, dstLine, tmpWidth, c1, c2);
92 template<
typename Pixel>
93 void RGBTriplet3xScaler<Pixel>::doScale1(FrameSource& src,
94 unsigned srcStartY,
unsigned ,
unsigned srcWidth,
95 ScalerOutput<Pixel>& dst,
unsigned dstStartY,
unsigned dstEndY,
96 PolyLineScaler<Pixel>&
scale)
100 auto [c1, c2] = calcBlur();
102 unsigned dstWidth = dst.getWidth();
103 unsigned tmpWidth = dstWidth / 3;
104 int scanlineFactor = settings.getScanlineFactor();
105 unsigned y = dstStartY;
106 auto* srcLine = src.getLinePtr(srcStartY++, srcWidth, buf);
107 auto* dstLine0 = dst.acquireLine(y + 0);
108 scaleLine(srcLine, dstLine0,
scale, tmpWidth, c1, c2);
110 Scale_1on1<Pixel>
copy;
111 auto* dstLine1 = dst.acquireLine(y + 1);
112 copy(dstLine0, dstLine1, dstWidth);
114 for (; (y + 4) < dstEndY; y += 3, srcStartY += 1) {
115 srcLine = src.getLinePtr(srcStartY, srcWidth, buf);
116 auto* dstLine3 = dst.acquireLine(y + 3);
117 scaleLine(srcLine, dstLine3,
scale, tmpWidth, c1, c2);
119 auto* dstLine4 = dst.acquireLine(y + 4);
120 copy(dstLine3, dstLine4, dstWidth);
122 auto* dstLine2 = dst.acquireLine(y + 2);
123 scanline.draw(dstLine0, dstLine3, dstLine2,
124 scanlineFactor, dstWidth);
126 dst.releaseLine(y + 0, dstLine0);
127 dst.releaseLine(y + 1, dstLine1);
128 dst.releaseLine(y + 2, dstLine2);
133 srcLine = src.getLinePtr(srcStartY, srcWidth, buf);
135 scaleLine(srcLine, buf2,
scale, tmpWidth, c1, c2);
136 auto* dstLine2 = dst.acquireLine(y + 2);
137 scanline.draw(dstLine0, buf2, dstLine2, scanlineFactor, dstWidth);
138 dst.releaseLine(y + 0, dstLine0);
139 dst.releaseLine(y + 1, dstLine1);
140 dst.releaseLine(y + 2, dstLine2);
143 template<
typename Pixel>
144 void RGBTriplet3xScaler<Pixel>::doScale2(FrameSource& src,
145 unsigned srcStartY,
unsigned ,
unsigned srcWidth,
146 ScalerOutput<Pixel>& dst,
unsigned dstStartY,
unsigned dstEndY,
147 PolyLineScaler<Pixel>&
scale)
150 auto [c1, c2] = calcBlur();
152 unsigned dstWidth = dst.getWidth();
153 unsigned tmpWidth = dstWidth / 3;
154 int scanlineFactor = settings.getScanlineFactor();
155 for (
unsigned srcY = srcStartY, dstY = dstStartY; dstY < dstEndY;
156 srcY += 2, dstY += 3) {
157 auto* srcLine0 = src.getLinePtr(srcY + 0, srcWidth, buf);
158 auto* dstLine0 = dst.acquireLine(dstY + 0);
159 scaleLine(srcLine0, dstLine0,
scale, tmpWidth, c1, c2);
161 auto* srcLine1 = src.getLinePtr(srcY + 1, srcWidth, buf);
162 auto* dstLine2 = dst.acquireLine(dstY + 2);
163 scaleLine(srcLine1, dstLine2,
scale, tmpWidth, c1, c2);
165 auto* dstLine1 = dst.acquireLine(dstY + 1);
166 scanline.draw(dstLine0, dstLine2, dstLine1,
167 scanlineFactor, dstWidth);
169 dst.releaseLine(dstY + 0, dstLine0);
170 dst.releaseLine(dstY + 1, dstLine1);
171 dst.releaseLine(dstY + 2, dstLine2);
175 template<
typename Pixel>
177 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
181 doScale1(src, srcStartY, srcEndY, srcWidth,
182 dst, dstStartY, dstEndY, op);
185 template<
typename Pixel>
187 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
191 doScale2(src, srcStartY, srcEndY, srcWidth,
192 dst, dstStartY, dstEndY, op);
195 template<
typename Pixel>
197 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
201 doScale1(src, srcStartY, srcEndY, srcWidth,
202 dst, dstStartY, dstEndY, op);
205 template<
typename Pixel>
207 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
211 doScale2(src, srcStartY, srcEndY, srcWidth,
212 dst, dstStartY, dstEndY, op);
215 template<
typename Pixel>
217 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
221 doScale1(src, srcStartY, srcEndY, srcWidth,
222 dst, dstStartY, dstEndY, op);
225 template<
typename Pixel>
227 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
231 doScale2(src, srcStartY, srcEndY, srcWidth,
232 dst, dstStartY, dstEndY, op);
235 template<
typename Pixel>
237 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
241 doScale1(src, srcStartY, srcEndY, srcWidth,
242 dst, dstStartY, dstEndY, op);
245 template<
typename Pixel>
247 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
251 doScale2(src, srcStartY, srcEndY, srcWidth,
252 dst, dstStartY, dstEndY, op);
255 template<
typename Pixel>
257 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
261 doScale1(src, srcStartY, srcEndY, srcWidth,
262 dst, dstStartY, dstEndY, op);
265 template<
typename Pixel>
267 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
271 doScale2(src, srcStartY, srcEndY, srcWidth,
272 dst, dstStartY, dstEndY, op);
275 template<
typename Pixel>
277 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
281 doScale1(src, srcStartY, srcEndY, srcWidth,
282 dst, dstStartY, dstEndY, op);
285 template<
typename Pixel>
287 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
291 doScale2(src, srcStartY, srcEndY, srcWidth,
292 dst, dstStartY, dstEndY, op);
295 template<
typename Pixel>
296 static constexpr
void fillLoop(
const Pixel* __restrict in,
Pixel* __restrict out,
302 for (
unsigned x = 3;
x < (dstWidth - 3);
x += 3) {
307 out[dstWidth - 3] = in[6];
308 out[dstWidth - 2] = in[7];
309 out[dstWidth - 1] = in[8];
312 template<
typename Pixel>
314 FrameSource& src,
unsigned srcStartY,
unsigned srcEndY,
317 auto [c1, c2] = calcBlur();
318 int scanlineFactor = settings.getScanlineFactor();
322 unsigned stopDstY = (dstEndY == dstHeight)
323 ? dstEndY : dstEndY - 3;
324 unsigned srcY = srcStartY, dstY = dstStartY;
325 for (; dstY < stopDstY; srcY += 1, dstY += 3) {
329 Pixel outNormal[3 * 3];
330 inNormal[0] = inNormal[1] = inNormal[2] = color;
331 rgbify(inNormal, outNormal, 3, c1, c2);
332 Pixel outScanline[3 * 3];
333 for (
auto [i, out] :
enumerate(outScanline)) {
334 out = scanline.darken(outNormal[i], scanlineFactor);
338 fillLoop(outNormal, dstLine0, dstWidth);
342 fillLoop(outNormal, dstLine1, dstWidth);
346 fillLoop(outScanline, dstLine2, dstWidth);
349 if (dstY != dstHeight) {
352 assert(nextLineWidth != 1);
353 this->dispatchScale(src, srcY, srcEndY, nextLineWidth,
358 template<
typename Pixel>
363 auto [c1, c2] = calcBlur();
364 int scanlineFactor = settings.getScanlineFactor();
366 for (
unsigned srcY = srcStartY, dstY = dstStartY;
367 dstY < dstEndY; srcY += 2, dstY += 3) {
372 Pixel out0Normal[3 * 3];
373 Pixel out1Normal[3 * 3];
374 Pixel outScanline[3 * 3];
376 inNormal[0] = inNormal[1] = inNormal[2] = color0;
377 rgbify(inNormal, out0Normal, 3, c1, c2);
378 inNormal[0] = inNormal[1] = inNormal[2] = color1;
379 rgbify(inNormal, out1Normal, 3, c1, c2);
381 for (
auto [i, out] :
enumerate(outScanline)) {
382 out = scanline.darken(
383 out0Normal[i], out1Normal[i],
388 fillLoop(out0Normal, dstLine0, dstWidth);
392 fillLoop(outScanline, dstLine1, dstWidth);
396 fillLoop(out1Normal, dstLine2, dstWidth);
401 template<
typename Pixel>
403 unsigned srcStartY,
unsigned srcEndY,
unsigned srcWidth,
409 this->dispatchScale(sf, srcStartY, srcEndY, srcWidth,
410 dst, dstStartY, dstEndY);
412 this->dispatchScale(src, srcStartY, srcEndY, srcWidth,
413 dst, dstStartY, dstEndY);
Interface for getting lines from a video frame.
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
virtual unsigned getLineWidth(unsigned line) const =0
Gets the number of display pixels on the given line.
Polymorphic wrapper around another line scaler.
void scaleBlank2to3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale4x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale8x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale8x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale2x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale1x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale2x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale4x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
RGBTriplet3xScaler(const PixelOperations< Pixel > &pixelOps, const RenderSettings &renderSettings)
void scale4x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scaleImage(FrameSource &src, const RawFrame *superImpose, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Scales the image in the given area, which must consist of lines which are all equally wide.
void scale2x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale1x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale2x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale4x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scaleBlank1to3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Class containing all settings for renderers.
Base class for 3x scalers.
virtual Pixel * acquireLine(unsigned y)=0
virtual unsigned getWidth() const =0
virtual unsigned getHeight() const =0
virtual void releaseLine(unsigned y, Pixel *buf)=0
This class represents a frame that is the (per-pixel) alpha-blend of a (laser-disc) video frame and a...
unsigned getLineWidth(unsigned line) const override
Gets the number of display pixels on the given line.
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
constexpr mat4 scale(const vec3 &xyz)
This file implemented 3 utility functions:
constexpr KeyMatrixPosition x
Keyboard bindings.
auto copy(InputRange &&range, OutputIter out)
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)