openMSX
Scaler3.cc
Go to the documentation of this file.
1 #include "Scaler3.hh"
2 #include "LineScalers.hh"
3 #include "RawFrame.hh"
4 #include "OutputSurface.hh"
6 #include "openmsx.hh"
7 #include "unreachable.hh"
8 #include "build-info.hh"
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  Pixel color = src.getLinePtr<Pixel>(srcY)[0];
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  Pixel color0 = src.getLinePtr<Pixel>(srcY + 0)[0];
40  Pixel color1 = src.getLinePtr<Pixel>(srcY + 1)[0];
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,
52  PolyLineScaler<Pixel>& scale)
53 {
54  Scale_1on1<Pixel> copy;
55  bool isStreaming = scale.isStreaming();
56  unsigned dstWidth = dst.getWidth();
57  for (unsigned dstY = dstStartY; dstY < dstEndY; dstY += 3, ++srcStartY) {
58  const Pixel* srcLine = src.getLinePtr<Pixel>(srcStartY, srcWidth);
59  Pixel* dstLine0 = dst.acquireLine(dstY + 0);
60  scale(srcLine, dstLine0, dstWidth);
61 
62  Pixel* dstLine1 = dst.acquireLine(dstY + 1);
63  if (isStreaming) {
64  scale(srcLine, dstLine1, dstWidth);
65  } else {
66  copy(dstLine0, dstLine1, dstWidth);
67  }
68 
69  Pixel* dstLine2 = dst.acquireLine(dstY + 2);
70  if (isStreaming) {
71  scale(srcLine, dstLine2, dstWidth);
72  } else {
73  copy(dstLine0, dstLine2, dstWidth);
74  }
75 
76  dst.releaseLine(dstY + 0, dstLine0);
77  dst.releaseLine(dstY + 1, dstLine1);
78  dst.releaseLine(dstY + 2, dstLine2);
79  }
80 }
81 
82 template <typename Pixel>
83 static void doScaleDV(FrameSource& src,
84  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
85  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY,
86  PixelOperations<Pixel> ops, PolyLineScaler<Pixel>& scale)
87 {
88  BlendLines<Pixel> blend(ops);
89  unsigned dstWidth = dst.getWidth();
90  for (unsigned srcY = srcStartY, dstY = dstStartY; dstY < dstEndY;
91  srcY += 2, dstY += 3) {
92  const Pixel* srcLine0 = src.getLinePtr<Pixel>(srcY + 0, srcWidth);
93  Pixel* dstLine0 = dst.acquireLine(dstY + 0);
94  scale(srcLine0, dstLine0, dstWidth);
95 
96  const Pixel* srcLine1 = src.getLinePtr<Pixel>(srcY + 1, srcWidth);
97  Pixel* dstLine2 = dst.acquireLine(dstY + 2);
98  scale(srcLine1, dstLine2, dstWidth);
99 
100  Pixel* dstLine1 = dst.acquireLine(dstY + 1);
101  blend(dstLine0, dstLine2, dstLine1, dstWidth);
102 
103  dst.releaseLine(dstY + 0, dstLine0);
104  dst.releaseLine(dstY + 1, dstLine1);
105  dst.releaseLine(dstY + 2, dstLine2);
106  }
107 }
108 
109 template <class Pixel>
111  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
112  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
113 {
115  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
116  dst, dstStartY, dstEndY, op);
117 }
118 
119 template <class Pixel>
121  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
122  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
123 {
125  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
126  dst, dstStartY, dstEndY, pixelOps, op);
127 }
128 
129 template <class Pixel>
131  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
132  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
133 {
135  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
136  dst, dstStartY, dstEndY, op);
137 }
138 
139 template <class Pixel>
141  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
142  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
143 {
145  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
146  dst, dstStartY, dstEndY, pixelOps, op);
147 }
148 
149 template <class Pixel>
151  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
152  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
153 {
155  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
156  dst, dstStartY, dstEndY, op);
157 }
158 
159 template <class Pixel>
161  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
162  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
163 {
165  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
166  dst, dstStartY, dstEndY, pixelOps, op);
167 }
168 
169 template <class Pixel>
171  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
172  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
173 {
175  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
176  dst, dstStartY, dstEndY, op);
177 }
178 
179 template <class Pixel>
181  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
182  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
183 {
185  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
186  dst, dstStartY, dstEndY, pixelOps, op);
187 }
188 
189 template <class Pixel>
191  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
192  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
193 {
195  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
196  dst, dstStartY, dstEndY, op);
197 }
198 
199 template <class Pixel>
201  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
202  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
203 {
205  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
206  dst, dstStartY, dstEndY, pixelOps, op);
207 }
208 
209 template <class Pixel>
211  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
212  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
213 {
215  doScale1<Pixel>(src, srcStartY, srcEndY, srcWidth,
216  dst, dstStartY, dstEndY, op);
217 }
218 
219 template <class Pixel>
221  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
222  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
223 {
225  doScaleDV<Pixel>(src, srcStartY, srcEndY, srcWidth,
226  dst, dstStartY, dstEndY, pixelOps, op);
227 }
228 
229 template <class Pixel>
231  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
232  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
233 {
234  if (src.getHeight() == 240) {
235  switch (srcWidth) {
236  case 1:
237  scaleBlank1to3(src, srcStartY, srcEndY,
238  dst, dstStartY, dstEndY);
239  break;
240  case 213:
241  scale2x1to9x3(src, srcStartY, srcEndY, srcWidth,
242  dst, dstStartY, dstEndY);
243  break;
244  case 320:
245  scale1x1to3x3(src, srcStartY, srcEndY, srcWidth,
246  dst, dstStartY, dstEndY);
247  break;
248  case 426:
249  scale4x1to9x3(src, srcStartY, srcEndY, srcWidth,
250  dst, dstStartY, dstEndY);
251  break;
252  case 640:
253  scale2x1to3x3(src, srcStartY, srcEndY, srcWidth,
254  dst, dstStartY, dstEndY);
255  break;
256  case 853:
257  scale8x1to9x3(src, srcStartY, srcEndY, srcWidth,
258  dst, dstStartY, dstEndY);
259  break;
260  case 1280:
261  scale4x1to3x3(src, srcStartY, srcEndY, srcWidth,
262  dst, dstStartY, dstEndY);
263  break;
264  default:
265  UNREACHABLE;
266  }
267  } else {
268  assert(src.getHeight() == 480);
269  switch (srcWidth) {
270  case 1:
271  scaleBlank2to3(src, srcStartY, srcEndY,
272  dst, dstStartY, dstEndY);
273  break;
274  case 213:
275  scale2x2to9x3(src, srcStartY, srcEndY, srcWidth,
276  dst, dstStartY, dstEndY);
277  break;
278  case 320:
279  scale1x2to3x3(src, srcStartY, srcEndY, srcWidth,
280  dst, dstStartY, dstEndY);
281  break;
282  case 426:
283  scale4x2to9x3(src, srcStartY, srcEndY, srcWidth,
284  dst, dstStartY, dstEndY);
285  break;
286  case 640:
287  scale2x2to3x3(src, srcStartY, srcEndY, srcWidth,
288  dst, dstStartY, dstEndY);
289  break;
290  case 853:
291  scale8x2to9x3(src, srcStartY, srcEndY, srcWidth,
292  dst, dstStartY, dstEndY);
293  break;
294  case 1280:
295  scale4x2to3x3(src, srcStartY, srcEndY, srcWidth,
296  dst, dstStartY, dstEndY);
297  break;
298  default:
299  UNREACHABLE;
300  }
301  }
302 }
303 
304 template <class Pixel>
305 void Scaler3<Pixel>::scaleImage(FrameSource& src, const RawFrame* superImpose,
306  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
307  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
308 {
309  if (superImpose) {
311  dst, *superImpose, pixelOps);
312  dispatchScale(src, srcStartY, srcEndY, srcWidth,
313  dst2, dstStartY, dstEndY);
314  } else {
315  dispatchScale(src, srcStartY, srcEndY, srcWidth,
316  dst, dstStartY, dstEndY);
317  }
318 }
319 
320 // Force template instantiation.
321 #if HAVE_16BPP
322 template class Scaler3<word>;
323 #endif
324 #if HAVE_32BPP
325 template class Scaler3<unsigned>;
326 #endif
327 
328 } // namespace openmsx