openMSX
Scaler1.cc
Go to the documentation of this file.
1 #include "Scaler1.hh"
2 #include "LineScalers.hh"
3 #include "FrameSource.hh"
5 #include "vla.hh"
6 #include "unreachable.hh"
7 #include "xrange.hh"
8 #include "build-info.hh"
9 #include <algorithm>
10 #include <cassert>
11 #include <cstdint>
12 
13 namespace openmsx {
14 
15 template<typename Pixel>
17  : pixelOps(pixelOps_)
18 {
19 }
20 
21 /*template<typename Pixel>
22 void Scaler1<Pixel>::averageHalve(const Pixel* pIn0, const Pixel* pIn1, Pixel* pOut, unsigned dstWidth)
23 {
24  // TODO SSE optimizations
25  // pure C++ version
26  for (auto i : xrange(dstWidth)) {
27  Pixel tmp0 = blend(pIn0[2 * i + 0], pIn0[2 * i + 1]);
28  Pixel tmp1 = blend(pIn1[2 * i + 0], pIn1[2 * i + 1]);
29  pOut[i] = blend(tmp0, tmp1);
30  }
31 }*/
32 
33 template<typename 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 += 1, dstY += 1) {
40  auto color = src.getLineColor<Pixel>(srcY);
41  dst.fillLine(dstY, color);
42  }
43 }
44 
45 template<typename Pixel>
47  FrameSource& src, unsigned srcStartY, unsigned /*srcEndY*/,
48  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
49 {
50  for (unsigned srcY = srcStartY, dstY = dstStartY;
51  dstY < dstEndY; srcY += 2, dstY += 1) {
52  auto color0 = src.getLineColor<Pixel>(srcY + 0);
53  auto color1 = src.getLineColor<Pixel>(srcY + 1);
54  Pixel color01 = pixelOps.template blend<1, 1>(color0, color1);
55  dst.fillLine(dstY, color01);
56  }
57 }
58 
59 template<typename Pixel>
60 static void doScale1(FrameSource& src,
61  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
62  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
64 {
65  VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
66  unsigned dstWidth = dst.getWidth();
67  for (unsigned srcY = srcStartY, dstY = dstStartY;
68  dstY < dstEndY; ++srcY, ++dstY) {
69  auto* srcLine = src.getLinePtr(srcY, srcWidth, buf);
70  auto* dstLine = dst.acquireLine(dstY);
71  scale(srcLine, dstLine, dstWidth);
72  dst.releaseLine(dstY, dstLine);
73  }
74 }
75 
76 template<typename Pixel>
77 static void doScaleDV(FrameSource& src,
78  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
79  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
80  PixelOperations<Pixel> ops, PolyLineScaler<Pixel>& scale)
81 {
82  BlendLines<Pixel> blend(ops);
83  unsigned dstWidth = dst.getWidth();
84  VLA_SSE_ALIGNED(Pixel, buf0, std::max(srcWidth, dstWidth));
85  VLA_SSE_ALIGNED(Pixel, buf1, srcWidth);
86  for (unsigned srcY = srcStartY, dstY = dstStartY;
87  dstY < dstEndY; srcY += 2, dstY += 1) {
88  auto* srcLine0 = src.getLinePtr(srcY + 0, srcWidth, buf0);
89  auto* srcLine1 = src.getLinePtr(srcY + 1, srcWidth, buf1);
90  auto* dstLine = dst.acquireLine(dstY);
91  scale(srcLine0, dstLine, dstWidth); // dstLine iso buf0
92  scale(srcLine1, buf0, dstWidth); // buf0 iso buf1
93  blend(dstLine, buf0, dstLine, dstWidth); // use input as output
94  dst.releaseLine(dstY, dstLine);
95  }
96 }
97 
98 
99 template<typename Pixel>
101  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
102  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
103 {
105  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
106  dst, dstStartY, dstEndY, op);
107 }
108 
109 template<typename Pixel>
111  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
112  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
113 {
115  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
116  dst, dstStartY, dstEndY, pixelOps, op);
117 }
118 
119 template<typename Pixel>
121  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
122  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
123 {
124  // Optimized variant: pass dstLine to getLinePtr(), so we can
125  // potentionally avoid the copy operation.
126  assert(dst.getWidth() == srcWidth);
128  for (unsigned srcY = srcStartY, dstY = dstStartY;
129  dstY < dstEndY; ++srcY, ++dstY) {
130  auto* dstLine = dst.acquireLine(dstY);
131  auto* srcLine = src.getLinePtr(srcY, srcWidth, dstLine);
132  if (srcLine != dstLine) copy(srcLine, dstLine, srcWidth);
133  dst.releaseLine(dstY, dstLine);
134  }
135 }
136 
137 template<typename Pixel>
139  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
140  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
141 {
142  // No need to scale to local buffer first, like doScaleDV does.
143  VLA_SSE_ALIGNED(Pixel, buf, srcWidth);
144  unsigned dstWidth = dst.getWidth();
145  BlendLines<Pixel> blend(pixelOps);
146  for (auto dstY : xrange(dstStartY, dstEndY)) {
147  auto* dstLine = dst.acquireLine(dstY);
148  auto* srcLine0 = src.getLinePtr(srcStartY++, srcWidth, dstLine);
149  auto* srcLine1 = src.getLinePtr(srcStartY++, srcWidth, buf);
150  blend(srcLine0, srcLine1, dstLine, dstWidth); // possibly srcLine0 == dstLine
151  dst.releaseLine(dstY, dstLine);
152  }
153 }
154 
155 template<typename Pixel>
157  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
158  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
159 {
161  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
162  dst, dstStartY, dstEndY, op);
163 }
164 
165 template<typename Pixel>
167  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
168  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
169 {
171  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
172  dst, dstStartY, dstEndY, pixelOps, op);
173 }
174 
175 template<typename Pixel>
177  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
178  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
179 {
181  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
182  dst, dstStartY, dstEndY, op);
183 }
184 
185 template<typename Pixel>
187  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
188  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
189 {
191  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
192  dst, dstStartY, dstEndY, pixelOps, op);
193 }
194 
195 template<typename Pixel>
197  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
198  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
199 {
201  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
202  dst, dstStartY, dstEndY, op);
203 }
204 
205 template<typename Pixel>
207  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
208  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
209 {
211  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
212  dst, dstStartY, dstEndY, pixelOps, op);
213 }
214 
215 template<typename Pixel>
217  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
218  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
219 {
221  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
222  dst, dstStartY, dstEndY, op);
223 }
224 
225 template<typename Pixel>
227  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
228  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
229 {
231  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
232  dst, dstStartY, dstEndY, pixelOps, op);
233 }
234 
235 template<typename Pixel>
237  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
238  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
239 {
240  if (src.getHeight() == 240) {
241  switch (srcWidth) {
242  case 1:
243  scaleBlank1to1(src, srcStartY, srcEndY,
244  dst, dstStartY, dstEndY);
245  break;
246  case 213:
247  scale2x1to3x1(src, srcStartY, srcEndY, srcWidth,
248  dst, dstStartY, dstEndY);
249  break;
250  case 320:
251  scale1x1to1x1(src, srcStartY, srcEndY, srcWidth,
252  dst, dstStartY, dstEndY);
253  break;
254  case 426:
255  scale4x1to3x1(src, srcStartY, srcEndY, srcWidth,
256  dst, dstStartY, dstEndY);
257  break;
258  case 640:
259  scale2x1to1x1(src, srcStartY, srcEndY, srcWidth,
260  dst, dstStartY, dstEndY);
261  break;
262  case 853:
263  scale8x1to3x1(src, srcStartY, srcEndY, srcWidth,
264  dst, dstStartY, dstEndY);
265  break;
266  case 1280:
267  scale4x1to1x1(src, srcStartY, srcEndY, srcWidth,
268  dst, dstStartY, dstEndY);
269  break;
270  default:
271  UNREACHABLE;
272  }
273  } else {
274  assert(src.getHeight() == 480);
275  switch (srcWidth) {
276  case 1:
277  scaleBlank2to1(src, srcStartY, srcEndY,
278  dst, dstStartY, dstEndY);
279  break;
280  case 213:
281  scale2x2to3x1(src, srcStartY, srcEndY, srcWidth,
282  dst, dstStartY, dstEndY);
283  break;
284  case 320:
285  scale1x2to1x1(src, srcStartY, srcEndY, srcWidth,
286  dst, dstStartY, dstEndY);
287  break;
288  case 426:
289  scale4x2to3x1(src, srcStartY, srcEndY, srcWidth,
290  dst, dstStartY, dstEndY);
291  break;
292  case 640:
293  scale2x2to1x1(src, srcStartY, srcEndY, srcWidth,
294  dst, dstStartY, dstEndY);
295  break;
296  case 853:
297  scale8x2to3x1(src, srcStartY, srcEndY, srcWidth,
298  dst, dstStartY, dstEndY);
299  break;
300  case 1280:
301  scale4x2to1x1(src, srcStartY, srcEndY, srcWidth,
302  dst, dstStartY, dstEndY);
303  break;
304  default:
305  UNREACHABLE;
306  }
307  }
308 }
309 
310 template<typename Pixel>
311 void Scaler1<Pixel>::scaleImage(FrameSource& src, const RawFrame* superImpose,
312  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
313  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
314 {
315  if (superImpose) {
317  dst, *superImpose, pixelOps);
318  dispatchScale(src, srcStartY, srcEndY, srcWidth,
319  dst2, dstStartY, dstEndY);
320  } else {
321  dispatchScale(src, srcStartY, srcEndY, srcWidth,
322  dst, dstStartY, dstEndY);
323  }
324 }
325 
326 // Force template instantiation.
327 #if HAVE_16BPP
328 template class Scaler1<uint16_t>;
329 #endif
330 #if HAVE_32BPP
331 template class Scaler1<uint32_t>;
332 #endif
333 
334 } // namespace openmsx
BlendLines functor Generate an output line that is an interpolation of two input lines.
Definition: LineScalers.hh:227
Interface for getting lines from a video frame.
Definition: FrameSource.hh:16
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
Definition: FrameSource.hh:75
unsigned getHeight() const
Gets the number of lines in this frame.
Definition: FrameSource.hh:45
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:92
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:14
virtual void scale4x2to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:166
virtual void scale1x2to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:138
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: Scaler1.cc:311
virtual void scale2x2to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:186
virtual void scaleBlank2to1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:46
virtual void scale2x1to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:176
virtual void scale2x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:100
virtual void scale2x2to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:110
void dispatchScale(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:236
virtual void scale8x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:196
virtual void scale1x1to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:120
virtual void scaleBlank1to1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:34
virtual void scale4x1to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:156
virtual void scale8x2to3x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:206
virtual void scale4x2to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:226
virtual void scale4x1to1x1(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY)
Definition: Scaler1.cc:216
Scaler1(const PixelOperations< Pixel > &pixelOps)
Definition: Scaler1.cc:16
virtual Pixel * acquireLine(unsigned y)=0
virtual unsigned getWidth() const =0
virtual void fillLine(unsigned y, Pixel color)=0
virtual void releaseLine(unsigned y, Pixel *buf)=0
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:287
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:179
#define UNREACHABLE
Definition: unreachable.hh:38
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44
constexpr auto xrange(T e)
Definition: xrange.hh:155