openMSX
FrameSource.cc
Go to the documentation of this file.
1 #include "FrameSource.hh"
2 #include "PixelOperations.hh"
3 #include "MemoryOps.hh"
4 #include "LineScalers.hh"
5 #include "openmsx.hh"
6 #include "unreachable.hh"
7 #include "build-info.hh"
8 #include "components.hh"
9 
10 namespace openmsx {
11 
12 FrameSource::FrameSource(const SDL_PixelFormat& format)
13  : pixelFormat(format)
14  , tempCounter(0)
15 {
16 }
17 
19 {
20  for (auto& t : tempBuffers) {
22  }
23 }
24 
25 void FrameSource::init(FieldType fieldType_)
26 {
27  fieldType = fieldType_;
28 }
29 
30 void FrameSource::setHeight(unsigned height_)
31 {
32  height = height_;
33 }
34 
35 template <typename Pixel>
36 const Pixel* FrameSource::blendLines(
37  const Pixel* line1, const Pixel* line2, unsigned width) const
38 {
39  PixelOperations<Pixel> pixelOps(pixelFormat);
40  BlendLines<Pixel> blend(pixelOps);
41  auto out = reinterpret_cast<Pixel*>(getTempBuffer());
42  blend(line1, line2, out, width);
43  return out;
44 }
45 
46 template <typename Pixel>
47 const Pixel* FrameSource::getLinePtr320_240(unsigned line) const
48 {
49  if (getHeight() == 240) {
50  return getLinePtr<Pixel>(line, 320);
51  } else {
52  assert(getHeight() == 480);
53  const Pixel* line1 = getLinePtr<Pixel>(2 * line + 0, 320);
54  const Pixel* line2 = getLinePtr<Pixel>(2 * line + 1, 320);
55  return blendLines(line1, line2, 320);
56  }
57 }
58 
59 template <typename Pixel>
60 const Pixel* FrameSource::getLinePtr640_480(unsigned line) const
61 {
62  if (getHeight() == 480) {
63  return getLinePtr<Pixel>(line, 640);
64  } else {
65  assert(getHeight() == 240);
66  return getLinePtr<Pixel>(line / 2, 640);
67  }
68 }
69 
70 template <typename Pixel>
71 const Pixel* FrameSource::getLinePtr960_720(unsigned line) const
72 {
73  if (getHeight() == 480) {
74  unsigned l2 = (2 * line) / 3;
75  const Pixel* line0 = getLinePtr<Pixel>(l2 + 0, 960);
76  if ((line % 3) == 1) {
77  const Pixel* line1 = getLinePtr<Pixel>(l2 + 1, 960);
78  return blendLines(line0, line1, 960);
79  } else {
80  return line0;
81  }
82  } else {
83  assert(getHeight() == 240);
84  return getLinePtr<Pixel>(line / 3, 960);
85  }
86 }
87 
89 {
90  if (tempCounter == tempBuffers.size()) {
91  unsigned size = 1280 * pixelFormat.BytesPerPixel;
92  void* buf = MemoryOps::mallocAligned(64, size);
93  tempBuffers.push_back(buf);
94  }
95  return tempBuffers[tempCounter++];
96 }
97 
99 {
100  tempCounter = 0; // reuse tempBuffers
101 }
102 
103 template <typename Pixel>
104 const Pixel* FrameSource::scaleLine(
105  const Pixel* in, unsigned inWidth, unsigned outWidth) const
106 {
107  PixelOperations<Pixel> pixelOps(pixelFormat);
108  auto out = reinterpret_cast<Pixel*>(getTempBuffer());
109 
110  // TODO is there a better way to implement this?
111  switch (inWidth) {
112  case 1: // blank
114  memset(out, outWidth, in[0]);
115  break;
116  case 213:
117  switch (outWidth) {
118  case 1:
119  out[0] = in[0];
120  break;
121  case 213:
122  UNREACHABLE;
123  case 320: {
124  Scale_2on3<Pixel> scale(pixelOps);
125  scale(in, out, outWidth);
126  break;
127  }
128  case 426: {
129  Scale_1on2<Pixel, false> scale; // no streaming
130  scale(in, out, outWidth);
131  break;
132  }
133  case 640: {
134  Scale_1on3<Pixel> scale;
135  scale(in, out, outWidth);
136  break;
137  }
138  case 853: {
139  Scale_1on4<Pixel> scale;
140  scale(in, out, outWidth);
141  break;
142  }
143  case 960: {
144  Scale_2on9<Pixel> scale(pixelOps);
145  scale(in, out, outWidth);
146  break;
147  }
148  case 1280: {
149  Scale_1on6<Pixel> scale;
150  scale(in, out, outWidth);
151  break;
152  }
153  default:
154  UNREACHABLE;
155  }
156  break;
157  case 320:
158  switch (outWidth) {
159  case 1:
160  out[0] = in[0];
161  break;
162  case 213: {
163  Scale_3on2<Pixel> scale(pixelOps);
164  scale(in, out, outWidth);
165  break;
166  }
167  case 320:
168  UNREACHABLE;
169  case 426: {
170  Scale_3on4<Pixel> scale(pixelOps);
171  scale(in, out, outWidth);
172  break;
173  }
174  case 640: {
175  Scale_1on2<Pixel, false> scale; // no streaming
176  scale(in, out, outWidth);
177  break;
178  }
179  case 853: {
180  Scale_3on8<Pixel> scale(pixelOps);
181  scale(in, out, outWidth);
182  break;
183  }
184  case 960: {
185  Scale_1on3<Pixel> scale;
186  scale(in, out, outWidth);
187  break;
188  }
189  case 1280: {
190  Scale_1on4<Pixel> scale;
191  scale(in, out, outWidth);
192  break;
193  }
194  default:
195  UNREACHABLE;
196  }
197  break;
198  case 426:
199  switch (outWidth) {
200  case 1:
201  out[0] = in[0];
202  break;
203  case 213: {
204  Scale_2on1<Pixel> scale(pixelOps);
205  scale(in, out, outWidth);
206  break;
207  }
208  case 320: {
209  Scale_4on3<Pixel> scale(pixelOps);
210  scale(in, out, outWidth);
211  break;
212  }
213  case 426:
214  UNREACHABLE;
215  case 640: {
216  Scale_2on3<Pixel> scale(pixelOps);
217  scale(in, out, outWidth);
218  break;
219  }
220  case 853: {
221  Scale_1on2<Pixel, false> scale; // no streaming
222  scale(in, out, outWidth);
223  break;
224  }
225  case 960: {
226  Scale_4on9<Pixel> scale(pixelOps);
227  scale(in, out, outWidth);
228  break;
229  }
230  case 1280: {
231  Scale_1on3<Pixel> scale;
232  scale(in, out, outWidth);
233  break;
234  }
235  default:
236  UNREACHABLE;
237  }
238  break;
239  case 640:
240  switch (outWidth) {
241  case 1:
242  out[0] = in[0];
243  break;
244  case 213: {
245  Scale_3on1<Pixel> scale(pixelOps);
246  scale(in, out, outWidth);
247  break;
248  }
249  case 320: {
250  Scale_2on1<Pixel> scale(pixelOps);
251  scale(in, out, outWidth);
252  break;
253  }
254  case 426: {
255  Scale_3on2<Pixel> scale(pixelOps);
256  scale(in, out, outWidth);
257  break;
258  }
259  case 640:
260  UNREACHABLE;
261  case 853: {
262  Scale_3on4<Pixel> scale(pixelOps);
263  scale(in, out, outWidth);
264  break;
265  }
266  case 960: {
267  Scale_2on3<Pixel> scale(pixelOps);
268  scale(in, out, outWidth);
269  break;
270  }
271  case 1280: {
272  Scale_1on2<Pixel, false> scale; // no streaming
273  scale(in, out, outWidth);
274  break;
275  }
276  default:
277  UNREACHABLE;
278  }
279  break;
280  case 853:
281  switch (outWidth) {
282  case 1:
283  out[0] = in[0];
284  break;
285  case 213: {
286  Scale_4on1<Pixel> scale(pixelOps);
287  scale(in, out, outWidth);
288  break;
289  }
290  case 320: {
291  Scale_8on3<Pixel> scale(pixelOps);
292  scale(in, out, outWidth);
293  break;
294  }
295  case 426: {
296  Scale_2on1<Pixel> scale(pixelOps);
297  scale(in, out, outWidth);
298  break;
299  }
300  case 640: {
301  Scale_4on3<Pixel> scale(pixelOps);
302  scale(in, out, outWidth);
303  break;
304  }
305  case 853:
306  UNREACHABLE;
307  case 960: {
308  Scale_8on9<Pixel> scale(pixelOps);
309  scale(in, out, outWidth);
310  break;
311  }
312  case 1280: {
313  Scale_2on3<Pixel> scale(pixelOps);
314  scale(in, out, outWidth);
315  break;
316  }
317  default:
318  UNREACHABLE;
319  }
320  break;
321  case 1280:
322  switch (outWidth) {
323  case 1:
324  out[0] = in[0];
325  break;
326  case 213: {
327  Scale_6on1<Pixel> scale(pixelOps);
328  scale(in, out, outWidth);
329  break;
330  }
331  case 320: {
332  Scale_4on1<Pixel> scale(pixelOps);
333  scale(in, out, outWidth);
334  break;
335  }
336  case 426: {
337  Scale_3on1<Pixel> scale(pixelOps);
338  scale(in, out, outWidth);
339  break;
340  }
341  case 640: {
342  Scale_2on1<Pixel> scale(pixelOps);
343  scale(in, out, outWidth);
344  break;
345  }
346  case 853: {
347  Scale_3on2<Pixel> scale(pixelOps);
348  scale(in, out, outWidth);
349  break;
350  }
351  case 960: {
352  Scale_4on3<Pixel> scale(pixelOps);
353  scale(in, out, outWidth);
354  break;
355  }
356  case 1280:
357  UNREACHABLE;
358  default:
359  UNREACHABLE;
360  }
361  break;
362  default:
363  UNREACHABLE;
364  }
365 
366  return out;
367 }
368 
369 
370 // Force template method instantiation
371 #if HAVE_16BPP
372 template const word* FrameSource::getLinePtr320_240<word>(unsigned) const;
373 template const word* FrameSource::getLinePtr640_480<word>(unsigned) const;
374 template const word* FrameSource::getLinePtr960_720<word>(unsigned) const;
375 template const word* FrameSource::scaleLine<word>(const word*, unsigned, unsigned) const;
376 #endif
377 #if HAVE_32BPP || COMPONENT_GL
378 template const unsigned* FrameSource::getLinePtr320_240<unsigned>(unsigned) const;
379 template const unsigned* FrameSource::getLinePtr640_480<unsigned>(unsigned) const;
380 template const unsigned* FrameSource::getLinePtr960_720<unsigned>(unsigned) const;
381 template const unsigned* FrameSource::scaleLine<unsigned>(const unsigned*, unsigned, unsigned) const;
382 #endif
383 
384 } // namespace openmsx