openMSX
Scaler2.cc
Go to the documentation of this file.
1#include "Scaler2.hh"
2#include "LineScalers.hh"
3#include "FrameSource.hh"
5#include "unreachable.hh"
6#include "vla.hh"
7#include "build-info.hh"
8#include <cassert>
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 += 2) {
26 auto color = src.getLineColor<Pixel>(srcY);
27 dst.fillLine(dstY + 0, color);
28 dst.fillLine(dstY + 1, color);
29 }
30}
31
32template<std::unsigned_integral Pixel>
34 FrameSource& src, unsigned srcStartY, unsigned /*srcEndY*/,
35 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
36{
37 for (unsigned srcY = srcStartY, dstY = dstStartY;
38 dstY < dstEndY; srcY += 1, dstY += 1) {
39 auto color = src.getLineColor<Pixel>(srcY);
40 dst.fillLine(dstY, color);
41 }
42}
43
44template<std::unsigned_integral Pixel>
45static void doScale1(FrameSource& src,
46 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
47 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
49{
50 VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
52 for (unsigned y = dstStartY; y < dstEndY; y += 2, ++srcStartY) {
53 auto srcLine = src.getLine(srcStartY, buf);
54 auto dstLine0 = dst.acquireLine(y + 0);
55 scale(srcLine, dstLine0);
56 auto dstLine1 = dst.acquireLine(y + 1);
57 copy(dstLine0, dstLine1);
58 dst.releaseLine(y + 0, dstLine0);
59 dst.releaseLine(y + 1, dstLine1);
60 }
61}
62
63template<std::unsigned_integral Pixel>
64static void doScale2(FrameSource& src,
65 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
66 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
67 PolyLineScaler<Pixel>& scale)
68{
69 VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
70 for (unsigned srcY = srcStartY, dstY = dstStartY;
71 dstY < dstEndY; ++dstY, ++srcY) {
72 auto srcLine = src.getLine(srcY, buf);
73 auto dstLine = dst.acquireLine(dstY);
74 scale(srcLine, dstLine);
75 dst.releaseLine(dstY, dstLine);
76 }
77}
78
79
80template<std::unsigned_integral Pixel>
82 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
83 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
84{
86 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
87 dst, dstStartY, dstEndY, op);
88}
89
90template<std::unsigned_integral Pixel>
92 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
93 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
94{
96 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
97 dst, dstStartY, dstEndY, op);
98}
99
100// TODO: In theory it's nice to have this as a fallback method, but in practice
101// all subclasses override this method, so should we keep it or not?
102// And if we keep it, should it be commented out like this until we
103// need it to reduce the executable size?
104// See also Scaler3::scale256.
105// TODO: Why won't it compile anymore without this method enabled?
106template<std::unsigned_integral Pixel>
108 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
109 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
110{
112 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
113 dst, dstStartY, dstEndY, op);
114}
115
116template<std::unsigned_integral Pixel>
118 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
119 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
120{
122 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
123 dst, dstStartY, dstEndY, op);
124}
125
126template<std::unsigned_integral Pixel>
128 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
129 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
130{
132 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
133 dst, dstStartY, dstEndY, op);
134}
135
136template<std::unsigned_integral Pixel>
138 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
139 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
140{
142 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
143 dst, dstStartY, dstEndY, op);
144}
145
146template<std::unsigned_integral Pixel>
148 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
149 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
150{
151 // Optimized variant: possibly avoid copy.
152 assert(dst.getWidth() == srcWidth); (void)srcWidth;
154 for (unsigned y = dstStartY; y < dstEndY; y += 2, ++srcStartY) {
155 auto dstLine0 = dst.acquireLine(y + 0);
156 auto srcLine = src.getLine(srcStartY, dstLine0);
157 if (srcLine.data() != dstLine0.data()) copy(srcLine, dstLine0);
158 auto dstLine1 = dst.acquireLine(y + 1);
159 copy(dstLine0, dstLine1);
160 dst.releaseLine(y + 0, dstLine0);
161 dst.releaseLine(y + 1, dstLine1);
162 }
163}
164
165template<std::unsigned_integral Pixel>
167 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
168 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
169{
170 // Optimized variant: possibly avoid copy.
171 assert(dst.getWidth() == srcWidth); (void)srcWidth;
173 for (unsigned srcY = srcStartY, dstY = dstStartY;
174 dstY < dstEndY; ++dstY, ++srcY) {
175 auto dstLine = dst.acquireLine(dstY);
176 auto srcLine = src.getLine(srcY, dstLine);
177 if (srcLine.data() != dstLine.data()) copy(srcLine, dstLine);
178 dst.releaseLine(dstY, dstLine);
179 }
180}
181
182template<std::unsigned_integral Pixel>
184 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
185 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
186{
188 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
189 dst, dstStartY, dstEndY, op);
190}
191
192template<std::unsigned_integral Pixel>
194 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
195 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
196{
198 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
199 dst, dstStartY, dstEndY, op);
200}
201
202template<std::unsigned_integral Pixel>
204 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
205 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
206{
208 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
209 dst, dstStartY, dstEndY, op);
210}
211
212template<std::unsigned_integral Pixel>
214 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
215 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
216{
218 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
219 dst, dstStartY, dstEndY, op);
220}
221
222template<std::unsigned_integral Pixel>
224 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
225 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
226{
227 if (src.getHeight() == 240) {
228 switch (srcWidth) {
229 case 1:
230 scaleBlank1to2(src, srcStartY, srcEndY,
231 dst, dstStartY, dstEndY);
232 break;
233 case 213:
234 scale1x1to3x2(src, srcStartY, srcEndY, srcWidth,
235 dst, dstStartY, dstEndY);
236 break;
237 case 320:
238 scale1x1to2x2(src, srcStartY, srcEndY, srcWidth,
239 dst, dstStartY, dstEndY);
240 break;
241 case 426:
242 scale2x1to3x2(src, srcStartY, srcEndY, srcWidth,
243 dst, dstStartY, dstEndY);
244 break;
245 case 640:
246 scale1x1to1x2(src, srcStartY, srcEndY, srcWidth,
247 dst, dstStartY, dstEndY);
248 break;
249 case 853:
250 scale4x1to3x2(src, srcStartY, srcEndY, srcWidth,
251 dst, dstStartY, dstEndY);
252 break;
253 case 1280:
254 scale2x1to1x2(src, srcStartY, srcEndY, srcWidth,
255 dst, dstStartY, dstEndY);
256 break;
257 default:
259 }
260 } else {
261 assert(src.getHeight() == 480);
262 switch (srcWidth) {
263 case 1:
264 scaleBlank1to1(src, srcStartY, srcEndY,
265 dst, dstStartY, dstEndY);
266 break;
267 case 213:
268 scale1x1to3x1(src, srcStartY, srcEndY, srcWidth,
269 dst, dstStartY, dstEndY);
270 break;
271 case 320:
272 scale1x1to2x1(src, srcStartY, srcEndY, srcWidth,
273 dst, dstStartY, dstEndY);
274 break;
275 case 426:
276 scale2x1to3x1(src, srcStartY, srcEndY, srcWidth,
277 dst, dstStartY, dstEndY);
278 break;
279 case 640:
280 scale1x1to1x1(src, srcStartY, srcEndY, srcWidth,
281 dst, dstStartY, dstEndY);
282 break;
283 case 853:
284 scale4x1to3x1(src, srcStartY, srcEndY, srcWidth,
285 dst, dstStartY, dstEndY);
286 break;
287 case 1280:
288 scale2x1to1x1(src, srcStartY, srcEndY, srcWidth,
289 dst, dstStartY, dstEndY);
290 break;
291 default:
293 }
294 }
295}
296
297template<std::unsigned_integral Pixel>
298void Scaler2<Pixel>::scaleImage(FrameSource& src, const RawFrame* superImpose,
299 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
300 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
301{
302 if (superImpose) {
304 dst, *superImpose, pixelOps);
305 dispatchScale(src, srcStartY, srcEndY, srcWidth,
306 dst2, dstStartY, dstEndY);
307 } else {
308 dispatchScale(src, srcStartY, srcEndY, srcWidth,
309 dst, dstStartY, dstEndY);
310 }
311}
312
313// Force template instantiation.
314#if HAVE_16BPP
315template class Scaler2<uint16_t>;
316#endif
317#if HAVE_32BPP
318template class Scaler2<uint32_t>;
319#endif
320
321} // 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 2x scalers.
Definition: Scaler2.hh:12
virtual void scale1x1to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:166
virtual void scale1x1to2x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:107
virtual void scale1x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:91
void dispatchScale(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:223
virtual void scale4x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:193
virtual void scaleBlank1to2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:20
virtual void scale1x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:81
virtual void scale2x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:127
virtual void scale1x1to2x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:117
virtual void scaleBlank1to1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:33
Scaler2(const PixelOperations< Pixel > &pixelOps)
Definition: Scaler2.cc:14
virtual void scale4x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:183
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: Scaler2.cc:298
virtual void scale1x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:147
virtual void scale2x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:137
virtual void scale2x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:203
virtual void scale2x1to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:213
virtual unsigned getWidth() const =0
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