openMSX
Scaler3.cc
Go to the documentation of this file.
1#include "Scaler3.hh"
2#include "LineScalers.hh"
3#include "FrameSource.hh"
5#include "unreachable.hh"
6#include "vla.hh"
7#include "xrange.hh"
8#include "build-info.hh"
9#include <cstdint>
10
11namespace openmsx {
12
13template<std::unsigned_integral Pixel>
15 : pixelOps(pixelOps_)
16{
17}
18
19template<std::unsigned_integral Pixel>
21 FrameSource& src, unsigned srcStartY, unsigned /*srcEndY*/,
22 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
23{
24 for (unsigned srcY = srcStartY, dstY = dstStartY;
25 dstY < dstEndY; srcY += 1, dstY += 3) {
26 auto color = src.getLineColor<Pixel>(srcY);
27 for (auto i : xrange(3)) {
28 dst.fillLine(dstY + i, color);
29 }
30 }
31}
32
33template<std::unsigned_integral Pixel>
35 FrameSource& src, unsigned srcStartY, unsigned /*srcEndY*/,
36 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
37{
38 for (unsigned srcY = srcStartY, dstY = dstStartY;
39 dstY < dstEndY; srcY += 2, dstY += 3) {
40 auto color0 = src.getLineColor<Pixel>(srcY + 0);
41 auto color1 = src.getLineColor<Pixel>(srcY + 1);
42 Pixel color01 = pixelOps.template blend<1, 1>(color0, color1);
43 dst.fillLine(dstY + 0, color0);
44 dst.fillLine(dstY + 1, color01);
45 dst.fillLine(dstY + 2, color1);
46 }
47}
48
49template<std::unsigned_integral Pixel>
50static void doScale1(FrameSource& src,
51 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
52 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
54{
55 VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
57 for (unsigned dstY = dstStartY; dstY < dstEndY; dstY += 3, ++srcStartY) {
58 auto srcLine = src.getLine(srcStartY, buf);
59 auto dstLine0 = dst.acquireLine(dstY + 0);
60 scale(srcLine, dstLine0);
61
62 auto dstLine1 = dst.acquireLine(dstY + 1);
63 copy(dstLine0, dstLine1);
64
65 auto dstLine2 = dst.acquireLine(dstY + 2);
66 copy(dstLine0, dstLine2);
67
68 dst.releaseLine(dstY + 0, dstLine0);
69 dst.releaseLine(dstY + 1, dstLine1);
70 dst.releaseLine(dstY + 2, dstLine2);
71 }
72}
73
74template<std::unsigned_integral Pixel>
75static void doScaleDV(FrameSource& src,
76 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
77 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
78 PixelOperations<Pixel> ops, PolyLineScaler<Pixel>& scale)
79{
80 VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
81 BlendLines<Pixel> blend(ops);
82 for (unsigned srcY = srcStartY, dstY = dstStartY; dstY < dstEndY;
83 srcY += 2, dstY += 3) {
84 auto srcLine0 = src.getLine(srcY + 0, buf);
85 auto dstLine0 = dst.acquireLine(dstY + 0);
86 scale(srcLine0, dstLine0);
87
88 auto srcLine1 = src.getLine(srcY + 1, buf);
89 auto dstLine2 = dst.acquireLine(dstY + 2);
90 scale(srcLine1, dstLine2);
91
92 auto dstLine1 = dst.acquireLine(dstY + 1);
93 blend(dstLine0, dstLine2, dstLine1);
94
95 dst.releaseLine(dstY + 0, dstLine0);
96 dst.releaseLine(dstY + 1, dstLine1);
97 dst.releaseLine(dstY + 2, dstLine2);
98 }
99}
100
101template<std::unsigned_integral Pixel>
103 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
104 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
105{
107 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
108 dst, dstStartY, dstEndY, op);
109}
110
111template<std::unsigned_integral Pixel>
113 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
114 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
115{
117 doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
118 dst, dstStartY, dstEndY, pixelOps, op);
119}
120
121template<std::unsigned_integral Pixel>
123 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
124 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
125{
127 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
128 dst, dstStartY, dstEndY, op);
129}
130
131template<std::unsigned_integral Pixel>
133 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
134 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
135{
137 doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
138 dst, dstStartY, dstEndY, pixelOps, op);
139}
140
141template<std::unsigned_integral Pixel>
143 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
144 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
145{
147 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
148 dst, dstStartY, dstEndY, op);
149}
150
151template<std::unsigned_integral Pixel>
153 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
154 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
155{
157 doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
158 dst, dstStartY, dstEndY, pixelOps, op);
159}
160
161template<std::unsigned_integral Pixel>
163 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
164 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
165{
167 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
168 dst, dstStartY, dstEndY, op);
169}
170
171template<std::unsigned_integral Pixel>
173 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
174 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
175{
177 doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
178 dst, dstStartY, dstEndY, pixelOps, op);
179}
180
181template<std::unsigned_integral Pixel>
183 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
184 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
185{
187 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
188 dst, dstStartY, dstEndY, op);
189}
190
191template<std::unsigned_integral Pixel>
193 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
194 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
195{
197 doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
198 dst, dstStartY, dstEndY, pixelOps, op);
199}
200
201template<std::unsigned_integral Pixel>
203 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
204 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
205{
207 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
208 dst, dstStartY, dstEndY, op);
209}
210
211template<std::unsigned_integral Pixel>
213 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
214 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
215{
217 doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
218 dst, dstStartY, dstEndY, pixelOps, op);
219}
220
221template<std::unsigned_integral Pixel>
223 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
224 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
225{
226 if (src.getHeight() == 240) {
227 switch (srcWidth) {
228 case 1:
229 scaleBlank1to3(src, srcStartY, srcEndY,
230 dst, dstStartY, dstEndY);
231 break;
232 case 213:
233 scale2x1to9x3(src, srcStartY, srcEndY, srcWidth,
234 dst, dstStartY, dstEndY);
235 break;
236 case 320:
237 scale1x1to3x3(src, srcStartY, srcEndY, srcWidth,
238 dst, dstStartY, dstEndY);
239 break;
240 case 426:
241 scale4x1to9x3(src, srcStartY, srcEndY, srcWidth,
242 dst, dstStartY, dstEndY);
243 break;
244 case 640:
245 scale2x1to3x3(src, srcStartY, srcEndY, srcWidth,
246 dst, dstStartY, dstEndY);
247 break;
248 case 853:
249 scale8x1to9x3(src, srcStartY, srcEndY, srcWidth,
250 dst, dstStartY, dstEndY);
251 break;
252 case 1280:
253 scale4x1to3x3(src, srcStartY, srcEndY, srcWidth,
254 dst, dstStartY, dstEndY);
255 break;
256 default:
258 }
259 } else {
260 assert(src.getHeight() == 480);
261 switch (srcWidth) {
262 case 1:
263 scaleBlank2to3(src, srcStartY, srcEndY,
264 dst, dstStartY, dstEndY);
265 break;
266 case 213:
267 scale2x2to9x3(src, srcStartY, srcEndY, srcWidth,
268 dst, dstStartY, dstEndY);
269 break;
270 case 320:
271 scale1x2to3x3(src, srcStartY, srcEndY, srcWidth,
272 dst, dstStartY, dstEndY);
273 break;
274 case 426:
275 scale4x2to9x3(src, srcStartY, srcEndY, srcWidth,
276 dst, dstStartY, dstEndY);
277 break;
278 case 640:
279 scale2x2to3x3(src, srcStartY, srcEndY, srcWidth,
280 dst, dstStartY, dstEndY);
281 break;
282 case 853:
283 scale8x2to9x3(src, srcStartY, srcEndY, srcWidth,
284 dst, dstStartY, dstEndY);
285 break;
286 case 1280:
287 scale4x2to3x3(src, srcStartY, srcEndY, srcWidth,
288 dst, dstStartY, dstEndY);
289 break;
290 default:
292 }
293 }
294}
295
296template<std::unsigned_integral Pixel>
297void Scaler3<Pixel>::scaleImage(FrameSource& src, const RawFrame* superImpose,
298 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
299 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
300{
301 if (superImpose) {
303 dst, *superImpose, pixelOps);
304 dispatchScale(src, srcStartY, srcEndY, srcWidth,
305 dst2, dstStartY, dstEndY);
306 } else {
307 dispatchScale(src, srcStartY, srcEndY, srcWidth,
308 dst, dstStartY, dstEndY);
309 }
310}
311
312// Force template instantiation.
313#if HAVE_16BPP
314template class Scaler3<uint16_t>;
315#endif
316#if HAVE_32BPP
317template class Scaler3<uint32_t>;
318#endif
319
320} // namespace openmsx
Interface for getting lines from a video frame.
Definition: FrameSource.hh:20
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
Definition: FrameSource.hh:79
std::span< const Pixel > getLine(int line, std::span< Pixel > buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:96
unsigned getHeight() const
Gets the number of lines in this frame.
Definition: FrameSource.hh:49
Polymorphic line scaler.
Definition: LineScalers.hh:286
Polymorphic wrapper around another line scaler.
Definition: LineScalers.hh:313
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition: RawFrame.hh:15
Base class for 3x scalers.
Definition: Scaler3.hh:12
virtual void scale2x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:112
virtual void scale1x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:122
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.
Definition: Scaler3.cc:297
virtual void scale4x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:152
virtual void scaleBlank1to3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:20
virtual void scale4x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:212
virtual void scale2x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:102
virtual void scale1x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:132
Scaler3(const PixelOperations< Pixel > &pixelOps)
Definition: Scaler3.cc:14
virtual void scale4x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:202
virtual void scale2x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:162
virtual void scale4x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:142
virtual void scale2x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:172
virtual void scale8x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:182
virtual void scaleBlank2to3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:34
virtual void scale8x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:192
void dispatchScale(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:222
virtual void fillLine(unsigned y, Pixel color)=0
virtual void releaseLine(unsigned y, std::span< Pixel > buf)=0
virtual std::span< Pixel > acquireLine(unsigned y)=0
constexpr mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint32_t Pixel
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:232
#define UNREACHABLE
Definition: unreachable.hh:38
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:50
constexpr auto xrange(T e)
Definition: xrange.hh:133