openMSX
FrameSource.cc
Go to the documentation of this file.
1#include "FrameSource.hh"
2
3#include "LineScalers.hh"
4
5#include "aligned.hh"
6#include "inplace_buffer.hh"
7#include "ranges.hh"
8#include "unreachable.hh"
9
10#include <array>
11#include <span>
12
13namespace openmsx {
14
16
17std::span<const Pixel, 320> FrameSource::getLinePtr320_240(unsigned line, std::span<Pixel, 320> buf0) const
18{
19 if (getHeight() == 240) {
20 auto r = getLine(line, std::span<Pixel>{buf0});
21 assert(r.size() == 320);
22 return std::span<const Pixel, 320>(r);
23 } else {
24 assert(getHeight() == 480);
25 ALIGNAS_SSE std::array<Pixel, 320> buf1;
26 auto line0 = getLine(2 * line + 0, std::span<Pixel>(buf0));
27 auto line1 = getLine(2 * line + 1, std::span<Pixel>(buf1));
28 blendLines(line0, line1, buf0); // possibly line0 == buf0
29 return buf0;
30 }
31}
32
33std::span<const Pixel, 640> FrameSource::getLinePtr640_480(unsigned line, std::span<Pixel, 640> buf) const
34{
35 if (getHeight() == 480) {
36 auto r = getLine(line, std::span<Pixel>(buf));
37 assert(r.size() == 640);
38 return std::span<const Pixel, 640>(r);
39 } else {
40 assert(getHeight() == 240);
41 auto r = getLine(line / 2, std::span<Pixel>(buf));
42 assert(r.size() == 640);
43 return std::span<const Pixel, 640>(r);
44 }
45}
46
47std::span<const Pixel, 960> FrameSource::getLinePtr960_720(unsigned line, std::span<Pixel, 960> buf0) const
48{
49 if (getHeight() == 480) {
50 unsigned l2 = (2 * line) / 3;
51 auto line0 = getLine(l2 + 0, std::span<Pixel>(buf0));
52 if ((line % 3) != 1) {
53 assert(line0.size() == 960);
54 return std::span<const Pixel, 960>(line0);
55 }
56 ALIGNAS_SSE std::array<Pixel, 960> buf1;
57 auto line1 = getLine(l2 + 1, std::span<Pixel>(buf1));
58 blendLines(line0, line1, buf0); // possibly line0 == buf0
59 return buf0;
60 } else {
61 assert(getHeight() == 240);
62 auto r = getLine(line / 3, std::span<Pixel>(buf0));
63 assert(r.size() == 960);
64 return std::span<const Pixel, 960>(r);
65 }
66}
67
69 std::span<const Pixel> in, std::span<Pixel> out) const
70{
72 if (in.data() == out.data()) [[unlikely]] {
73 // Only happens in case getLineInfo() already used buf.
74 // E.g. when a line of a SuperImposedFrame also needs to be
75 // scaled.
76 // TODO If the LineScaler routines can work in-place then this
77 // copy can be avoided.
78 ranges::copy(in, tmpBuf);
79 in = tmpBuf;
80 }
81
82 // TODO is there a better way to implement this?
83 switch (in.size()) {
84 case 1: // blank
85 ranges::fill(out, in[0]);
86 break;
87 case 213:
88 switch (out.size()) {
89 case 1: out[0] = in[0]; break;
90 case 213: UNREACHABLE;
91 case 320: scale_2on3(in, out); break;
92 case 426: scale_1on2(in, out); break;
93 case 640: scale_1on3(in, out); break;
94 case 853: scale_1on4(in, out); break;
95 case 960: scale_2on9(in, out); break;
96 case 1280: scale_1on6(in, out); break;
97 default: UNREACHABLE;
98 }
99 break;
100 case 320:
101 switch (out.size()) {
102 case 1: out[0] = in[0]; break;
103 case 213: scale_3on2(in, out); break;
104 case 320: UNREACHABLE;
105 case 426: scale_3on4(in, out); break;
106 case 640: scale_1on2(in, out); break;
107 case 853: scale_3on8(in, out); break;
108 case 960: scale_1on3(in, out); break;
109 case 1280: scale_1on4(in, out); break;
110 default: UNREACHABLE;
111 }
112 break;
113 case 426:
114 switch (out.size()) {
115 case 1: out[0] = in[0]; break;
116 case 213: scale_2on1(in, out); break;
117 case 320: scale_4on3(in, out); break;
118 case 426: UNREACHABLE;
119 case 640: scale_2on3(in, out); break;
120 case 853: scale_1on2(in, out); break;
121 case 960: scale_4on9(in, out); break;
122 case 1280: scale_1on3(in, out); break;
123 default: UNREACHABLE;
124 }
125 break;
126 case 640:
127 switch (out.size()) {
128 case 1: out[0] = in[0]; break;
129 case 213: scale_3on1(in, out); break;
130 case 320: scale_2on1(in, out); break;
131 case 426: scale_3on2(in, out); break;
132 case 640: UNREACHABLE;
133 case 853: scale_3on4(in, out); break;
134 case 960: scale_2on3(in, out); break;
135 case 1280: scale_1on2(in, out); break;
136 default: UNREACHABLE;
137 }
138 break;
139 case 853:
140 switch (out.size()) {
141 case 1: out[0] = in[0]; break;
142 case 213: scale_4on1(in, out); break;
143 case 320: scale_8on3(in, out); break;
144 case 426: scale_2on1(in, out); break;
145 case 640: scale_4on3(in, out); break;
146 case 853: UNREACHABLE;
147 case 960: scale_8on9(in, out); break;
148 case 1280: scale_2on3(in, out); break;
149 default: UNREACHABLE;
150 }
151 break;
152 case 1280:
153 switch (out.size()) {
154 case 1: out[0] = in[0]; break;
155 case 213: scale_6on1(in, out); break;
156 case 320: scale_4on1(in, out); break;
157 case 426: scale_3on1(in, out); break;
158 case 640: scale_2on1(in, out); break;
159 case 853: scale_3on2(in, out); break;
160 case 960: scale_4on3(in, out); break;
161 case 1280: UNREACHABLE;
162 default: UNREACHABLE;
163 }
164 break;
165 default:
167 }
168}
169
170} // namespace openmsx
#define ALIGNAS_SSE
Definition aligned.hh:24
std::span< const Pixel > getLine(int line, std::span< Pixel > buf) const
Gets a pointer to the pixels of the given line number.
std::span< const Pixel, 320 > getLinePtr320_240(unsigned line, std::span< Pixel, 320 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 320x240 pixels.
std::span< const Pixel, 960 > getLinePtr960_720(unsigned line, std::span< Pixel, 960 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 960x720 pixels.
void scaleLine(std::span< const Pixel > in, std::span< Pixel > out) const
std::span< const Pixel, 640 > getLinePtr640_480(unsigned line, std::span< Pixel, 640 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 640x480 pixels.
unsigned getHeight() const
Gets the number of lines in this frame.
This file implemented 3 utility functions:
Definition Autofire.cc:11
void scale_3on1(std::span< const Pixel > in, std::span< Pixel > out)
void blendLines(std::span< const Pixel > in1, std::span< const Pixel > in2, std::span< Pixel > out)
BlendLines functor Generate an output line that is an interpolation of two input lines.
void scale_2on1(std::span< const Pixel > in, std::span< Pixel > out)
void scale_2on3(std::span< const Pixel > in, std::span< Pixel > out)
void scale_4on9(std::span< const Pixel > in, std::span< Pixel > out)
void scale_6on1(std::span< const Pixel > in, std::span< Pixel > out)
void scale_1on2(std::span< const Pixel > in, std::span< Pixel > out)
void scale_1on3(std::span< const Pixel > in, std::span< Pixel > out)
Scale_XonY functions Transforms an input line of pixel to an output line (possibly) with a different ...
void scale_4on3(std::span< const Pixel > in, std::span< Pixel > out)
void scale_3on2(std::span< const Pixel > in, std::span< Pixel > out)
void scale_3on8(std::span< const Pixel > in, std::span< Pixel > out)
void scale_2on9(std::span< const Pixel > in, std::span< Pixel > out)
void scale_1on4(std::span< const Pixel > in, std::span< Pixel > out)
CharacterConverter::Pixel Pixel
void scale_1on6(std::span< const Pixel > in, std::span< Pixel > out)
void scale_4on1(std::span< const Pixel > in, std::span< Pixel > out)
void scale_3on4(std::span< const Pixel > in, std::span< Pixel > out)
void scale_8on9(std::span< const Pixel > in, std::span< Pixel > out)
void scale_8on3(std::span< const Pixel > in, std::span< Pixel > out)
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:315
constexpr auto copy(InputRange &&range, OutputIter out)
Definition ranges.hh:252
#define UNREACHABLE