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 unsigned dstWidth = dst.getWidth();
53 for (unsigned y = dstStartY; y < dstEndY; y += 2, ++srcStartY) {
54 auto* srcLine = src.getLinePtr(srcStartY, srcWidth, buf);
55 auto* dstLine0 = dst.acquireLine(y + 0);
56 scale(srcLine, dstLine0, dstWidth);
57 auto* dstLine1 = dst.acquireLine(y + 1);
58 copy(dstLine0, dstLine1, dstWidth);
59 dst.releaseLine(y + 0, dstLine0);
60 dst.releaseLine(y + 1, dstLine1);
61 }
62}
63
64template<std::unsigned_integral Pixel>
65static void doScale2(FrameSource& src,
66 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
67 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
68 PolyLineScaler<Pixel>& scale)
69{
70 VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
71 unsigned dstWidth = dst.getWidth();
72 for (unsigned srcY = srcStartY, dstY = dstStartY;
73 dstY < dstEndY; ++dstY, ++srcY) {
74 auto* srcLine = src.getLinePtr(srcY, srcWidth, buf);
75 auto* dstLine = dst.acquireLine(dstY);
76 scale(srcLine, dstLine, dstWidth);
77 dst.releaseLine(dstY, dstLine);
78 }
79}
80
81
82template<std::unsigned_integral Pixel>
84 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
85 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
86{
88 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
89 dst, dstStartY, dstEndY, op);
90}
91
92template<std::unsigned_integral Pixel>
94 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
95 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
96{
98 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
99 dst, dstStartY, dstEndY, op);
100}
101
102// TODO: In theory it's nice to have this as a fallback method, but in practice
103// all subclasses override this method, so should we keep it or not?
104// And if we keep it, should it be commented out like this until we
105// need it to reduce the executable size?
106// See also Scaler3::scale256.
107// TODO: Why won't it compile anymore without this method enabled?
108template<std::unsigned_integral Pixel>
110 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
111 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
112{
114 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
115 dst, dstStartY, dstEndY, op);
116}
117
118template<std::unsigned_integral Pixel>
120 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
121 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
122{
124 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
125 dst, dstStartY, dstEndY, op);
126}
127
128template<std::unsigned_integral Pixel>
130 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
131 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
132{
134 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
135 dst, dstStartY, dstEndY, op);
136}
137
138template<std::unsigned_integral Pixel>
140 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
141 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
142{
144 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
145 dst, dstStartY, dstEndY, op);
146}
147
148template<std::unsigned_integral Pixel>
150 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
151 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
152{
153 // Optimized variant: possibly avoid copy.
154 assert(dst.getWidth() == srcWidth);
156 for (unsigned y = dstStartY; y < dstEndY; y += 2, ++srcStartY) {
157 auto* dstLine0 = dst.acquireLine(y + 0);
158 auto* srcLine = src.getLinePtr(srcStartY, srcWidth, dstLine0);
159 if (srcLine != dstLine0) copy(srcLine, dstLine0, srcWidth);
160 auto* dstLine1 = dst.acquireLine(y + 1);
161 copy(dstLine0, dstLine1, srcWidth);
162 dst.releaseLine(y + 0, dstLine0);
163 dst.releaseLine(y + 1, dstLine1);
164 }
165}
166
167template<std::unsigned_integral Pixel>
169 unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
170 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
171{
172 // Optimized variant: possibly avoid copy.
173 assert(dst.getWidth() == srcWidth);
175 for (unsigned srcY = srcStartY, dstY = dstStartY;
176 dstY < dstEndY; ++dstY, ++srcY) {
177 auto* dstLine = dst.acquireLine(dstY);
178 auto* srcLine = src.getLinePtr(srcY, srcWidth, dstLine);
179 if (srcLine != dstLine) copy(srcLine, dstLine, srcWidth);
180 dst.releaseLine(dstY, dstLine);
181 }
182}
183
184template<std::unsigned_integral Pixel>
186 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
187 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
188{
190 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
191 dst, dstStartY, dstEndY, op);
192}
193
194template<std::unsigned_integral Pixel>
196 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
197 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
198{
200 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
201 dst, dstStartY, dstEndY, op);
202}
203
204template<std::unsigned_integral Pixel>
206 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
207 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
208{
210 doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
211 dst, dstStartY, dstEndY, op);
212}
213
214template<std::unsigned_integral Pixel>
216 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
217 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
218{
220 doScale2<Pixel>(src, srcStartY, srcEndY, srcWidth,
221 dst, dstStartY, dstEndY, op);
222}
223
224template<std::unsigned_integral Pixel>
226 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
227 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
228{
229 if (src.getHeight() == 240) {
230 switch (srcWidth) {
231 case 1:
232 scaleBlank1to2(src, srcStartY, srcEndY,
233 dst, dstStartY, dstEndY);
234 break;
235 case 213:
236 scale1x1to3x2(src, srcStartY, srcEndY, srcWidth,
237 dst, dstStartY, dstEndY);
238 break;
239 case 320:
240 scale1x1to2x2(src, srcStartY, srcEndY, srcWidth,
241 dst, dstStartY, dstEndY);
242 break;
243 case 426:
244 scale2x1to3x2(src, srcStartY, srcEndY, srcWidth,
245 dst, dstStartY, dstEndY);
246 break;
247 case 640:
248 scale1x1to1x2(src, srcStartY, srcEndY, srcWidth,
249 dst, dstStartY, dstEndY);
250 break;
251 case 853:
252 scale4x1to3x2(src, srcStartY, srcEndY, srcWidth,
253 dst, dstStartY, dstEndY);
254 break;
255 case 1280:
256 scale2x1to1x2(src, srcStartY, srcEndY, srcWidth,
257 dst, dstStartY, dstEndY);
258 break;
259 default:
261 }
262 } else {
263 assert(src.getHeight() == 480);
264 switch (srcWidth) {
265 case 1:
266 scaleBlank1to1(src, srcStartY, srcEndY,
267 dst, dstStartY, dstEndY);
268 break;
269 case 213:
270 scale1x1to3x1(src, srcStartY, srcEndY, srcWidth,
271 dst, dstStartY, dstEndY);
272 break;
273 case 320:
274 scale1x1to2x1(src, srcStartY, srcEndY, srcWidth,
275 dst, dstStartY, dstEndY);
276 break;
277 case 426:
278 scale2x1to3x1(src, srcStartY, srcEndY, srcWidth,
279 dst, dstStartY, dstEndY);
280 break;
281 case 640:
282 scale1x1to1x1(src, srcStartY, srcEndY, srcWidth,
283 dst, dstStartY, dstEndY);
284 break;
285 case 853:
286 scale4x1to3x1(src, srcStartY, srcEndY, srcWidth,
287 dst, dstStartY, dstEndY);
288 break;
289 case 1280:
290 scale2x1to1x1(src, srcStartY, srcEndY, srcWidth,
291 dst, dstStartY, dstEndY);
292 break;
293 default:
295 }
296 }
297}
298
299template<std::unsigned_integral Pixel>
300void Scaler2<Pixel>::scaleImage(FrameSource& src, const RawFrame* superImpose,
301 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
302 ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
303{
304 if (superImpose) {
306 dst, *superImpose, pixelOps);
307 dispatchScale(src, srcStartY, srcEndY, srcWidth,
308 dst2, dstStartY, dstEndY);
309 } else {
310 dispatchScale(src, srcStartY, srcEndY, srcWidth,
311 dst, dstStartY, dstEndY);
312 }
313}
314
315// Force template instantiation.
316#if HAVE_16BPP
317template class Scaler2<uint16_t>;
318#endif
319#if HAVE_32BPP
320template class Scaler2<uint32_t>;
321#endif
322
323} // namespace openmsx
Interface for getting lines from a video frame.
Definition: FrameSource.hh:17
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
Definition: FrameSource.hh:76
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:93
unsigned getHeight() const
Gets the number of lines in this frame.
Definition: FrameSource.hh:46
Polymorphic line scaler.
Definition: LineScalers.hh:285
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:168
virtual void scale1x1to2x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:109
virtual void scale1x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:93
void dispatchScale(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:225
virtual void scale4x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:195
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:83
virtual void scale2x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:129
virtual void scale1x1to2x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:119
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:185
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:300
virtual void scale1x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:149
virtual void scale2x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:139
virtual void scale2x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:205
virtual void scale2x1to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler2.cc:215
virtual unsigned getWidth() const =0
virtual Pixel * acquireLine(unsigned y)=0
virtual void fillLine(unsigned y, Pixel color)=0
virtual void releaseLine(unsigned y, Pixel *buf)=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:208
#define UNREACHABLE
Definition: unreachable.hh:38
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44