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 "build-info.hh"
8 #include <cstdint>
9 
10 namespace openmsx {
11 
12 template <class Pixel>
14  : pixelOps(pixelOps_)
15 {
16 }
17 
18 template <class Pixel>
20  FrameSource& src, unsigned srcStartY, unsigned /*srcEndY*/,
21  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
22 {
23  for (unsigned srcY = srcStartY, dstY = dstStartY;
24  dstY < dstEndY; srcY += 1, dstY += 3) {
25  auto color = src.getLineColor<Pixel>(srcY);
26  for (int i = 0; i < 3; ++i) {
27  dst.fillLine(dstY + i, color);
28  }
29  }
30 }
31 
32 template <class 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 += 2, dstY += 3) {
39  auto color0 = src.getLineColor<Pixel>(srcY + 0);
40  auto color1 = src.getLineColor<Pixel>(srcY + 1);
41  Pixel color01 = pixelOps.template blend<1, 1>(color0, color1);
42  dst.fillLine(dstY + 0, color0);
43  dst.fillLine(dstY + 1, color01);
44  dst.fillLine(dstY + 2, color1);
45  }
46 }
47 
48 template <typename Pixel>
49 static void doScale1(FrameSource& src,
50  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
51  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
53 {
54  VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
56  unsigned dstWidth = dst.getWidth();
57  for (unsigned dstY = dstStartY; dstY < dstEndY; dstY += 3, ++srcStartY) {
58  auto* srcLine = src.getLinePtr(srcStartY, srcWidth, buf);
59  auto* dstLine0 = dst.acquireLine(dstY + 0);
60  scale(srcLine, dstLine0, dstWidth);
61 
62  auto* dstLine1 = dst.acquireLine(dstY + 1);
63  copy(dstLine0, dstLine1, dstWidth);
64 
65  auto* dstLine2 = dst.acquireLine(dstY + 2);
66  copy(dstLine0, dstLine2, dstWidth);
67 
68  dst.releaseLine(dstY + 0, dstLine0);
69  dst.releaseLine(dstY + 1, dstLine1);
70  dst.releaseLine(dstY + 2, dstLine2);
71  }
72 }
73 
74 template <typename Pixel>
75 static void doScaleDV(FrameSource& src,
76  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
77  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
79 {
80  VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
81  BlendLines<Pixel> blend(ops);
82  unsigned dstWidth = dst.getWidth();
83  for (unsigned srcY = srcStartY, dstY = dstStartY; dstY < dstEndY;
84  srcY += 2, dstY += 3) {
85  auto* srcLine0 = src.getLinePtr(srcY + 0, srcWidth, buf);
86  auto* dstLine0 = dst.acquireLine(dstY + 0);
87  scale(srcLine0, dstLine0, dstWidth);
88 
89  auto* srcLine1 = src.getLinePtr(srcY + 1, srcWidth, buf);
90  auto* dstLine2 = dst.acquireLine(dstY + 2);
91  scale(srcLine1, dstLine2, dstWidth);
92 
93  auto* dstLine1 = dst.acquireLine(dstY + 1);
94  blend(dstLine0, dstLine2, dstLine1, dstWidth);
95 
96  dst.releaseLine(dstY + 0, dstLine0);
97  dst.releaseLine(dstY + 1, dstLine1);
98  dst.releaseLine(dstY + 2, dstLine2);
99  }
100 }
101 
102 template <class Pixel>
104  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
105  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
106 {
108  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
109  dst, dstStartY, dstEndY, op);
110 }
111 
112 template <class Pixel>
114  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
115  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
116 {
118  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
119  dst, dstStartY, dstEndY, pixelOps, op);
120 }
121 
122 template <class Pixel>
124  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
125  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
126 {
128  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
129  dst, dstStartY, dstEndY, op);
130 }
131 
132 template <class Pixel>
134  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
135  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
136 {
138  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
139  dst, dstStartY, dstEndY, pixelOps, op);
140 }
141 
142 template <class Pixel>
144  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
145  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
146 {
148  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
149  dst, dstStartY, dstEndY, op);
150 }
151 
152 template <class Pixel>
154  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
155  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
156 {
158  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
159  dst, dstStartY, dstEndY, pixelOps, op);
160 }
161 
162 template <class Pixel>
164  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
165  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
166 {
168  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
169  dst, dstStartY, dstEndY, op);
170 }
171 
172 template <class Pixel>
174  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
175  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
176 {
178  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
179  dst, dstStartY, dstEndY, pixelOps, op);
180 }
181 
182 template <class 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 
192 template <class Pixel>
194  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
195  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
196 {
198  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
199  dst, dstStartY, dstEndY, pixelOps, op);
200 }
201 
202 template <class 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 
212 template <class Pixel>
214  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
215  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
216 {
218  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
219  dst, dstStartY, dstEndY, pixelOps, op);
220 }
221 
222 template <class 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  scaleBlank1to3(src, srcStartY, srcEndY,
231  dst, dstStartY, dstEndY);
232  break;
233  case 213:
234  scale2x1to9x3(src, srcStartY, srcEndY, srcWidth,
235  dst, dstStartY, dstEndY);
236  break;
237  case 320:
238  scale1x1to3x3(src, srcStartY, srcEndY, srcWidth,
239  dst, dstStartY, dstEndY);
240  break;
241  case 426:
242  scale4x1to9x3(src, srcStartY, srcEndY, srcWidth,
243  dst, dstStartY, dstEndY);
244  break;
245  case 640:
246  scale2x1to3x3(src, srcStartY, srcEndY, srcWidth,
247  dst, dstStartY, dstEndY);
248  break;
249  case 853:
250  scale8x1to9x3(src, srcStartY, srcEndY, srcWidth,
251  dst, dstStartY, dstEndY);
252  break;
253  case 1280:
254  scale4x1to3x3(src, srcStartY, srcEndY, srcWidth,
255  dst, dstStartY, dstEndY);
256  break;
257  default:
258  UNREACHABLE;
259  }
260  } else {
261  assert(src.getHeight() == 480);
262  switch (srcWidth) {
263  case 1:
264  scaleBlank2to3(src, srcStartY, srcEndY,
265  dst, dstStartY, dstEndY);
266  break;
267  case 213:
268  scale2x2to9x3(src, srcStartY, srcEndY, srcWidth,
269  dst, dstStartY, dstEndY);
270  break;
271  case 320:
272  scale1x2to3x3(src, srcStartY, srcEndY, srcWidth,
273  dst, dstStartY, dstEndY);
274  break;
275  case 426:
276  scale4x2to9x3(src, srcStartY, srcEndY, srcWidth,
277  dst, dstStartY, dstEndY);
278  break;
279  case 640:
280  scale2x2to3x3(src, srcStartY, srcEndY, srcWidth,
281  dst, dstStartY, dstEndY);
282  break;
283  case 853:
284  scale8x2to9x3(src, srcStartY, srcEndY, srcWidth,
285  dst, dstStartY, dstEndY);
286  break;
287  case 1280:
288  scale4x2to3x3(src, srcStartY, srcEndY, srcWidth,
289  dst, dstStartY, dstEndY);
290  break;
291  default:
292  UNREACHABLE;
293  }
294  }
295 }
296 
297 template <class Pixel>
298 void Scaler3<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
315 template class Scaler3<uint16_t>;
316 #endif
317 #if HAVE_32BPP
318 template class Scaler3<uint32_t>;
319 #endif
320 
321 } // namespace openmsx
BlendLines functor Generate an output line that is an iterpolation of two input lines.
Definition: LineScalers.hh:224
virtual void scale1x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:133
virtual void scale4x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:203
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:149
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
Definition: FrameSource.hh:74
virtual void fillLine(unsigned y, Pixel color)=0
virtual Pixel * acquireLine(unsigned y)=0
Polymorphic wrapper around another line scaler.
Definition: LineScalers.hh:310
virtual void scaleBlank2to3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:33
virtual void scale2x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:113
Polymorphic line scaler.
Definition: LineScalers.hh:282
uint32_t Pixel
Interface for getting lines from a video frame.
Definition: FrameSource.hh:14
mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition: RawFrame.hh:25
const PixelOperations< Pixel > pixelOps
Definition: Scaler3.hh:67
virtual void scale4x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:153
virtual void scale2x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:173
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
virtual void scale4x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:143
virtual void releaseLine(unsigned y, Pixel *buf)=0
virtual void scale8x2to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:193
virtual void scaleBlank1to3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:19
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:91
virtual void scale1x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:123
virtual void scale2x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:103
virtual void scale2x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:163
void dispatchScale(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:223
Scaler3(const PixelOperations< Pixel > &pixelOps)
Definition: Scaler3.cc:13
virtual unsigned getWidth() const =0
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:298
virtual void scale8x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:183
unsigned getHeight() const
Gets the number of lines in this frame.
Definition: FrameSource.hh:44
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44
virtual void scale4x2to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler3.cc:213
Base class for 3x scalers.
Definition: Scaler3.hh:11
#define UNREACHABLE
Definition: unreachable.hh:38