openMSX
StretchScalerOutput.cc
Go to the documentation of this file.
3#include "LineScalers.hh"
4#include "PixelOperations.hh"
5#include "MemoryOps.hh"
6#include "build-info.hh"
7#include <cstdint>
8#include <memory>
9#include <vector>
10
11namespace openmsx {
12
13template<std::unsigned_integral Pixel>
15{
16public:
19 ~StretchScalerOutputBase() override;
22
23 [[nodiscard]] unsigned getWidth() const final;
24 [[nodiscard]] unsigned getHeight() const final;
25
26 void frameStart() final { output.frameStart(); }
27 void frameStop() final { output.frameStop(); }
28
29 [[nodiscard]] std::span<Pixel> acquireLine(unsigned y) final;
30 void fillLine(unsigned y, Pixel color) override;
31
32protected:
33 [[nodiscard]] std::span<Pixel> releasePre(unsigned y, std::span<Pixel> buf);
34 void releasePost(unsigned y, std::span<Pixel> dstLine);
35
37
38private:
40 std::vector<Pixel*> pool;
41};
42
43template<std::unsigned_integral Pixel>
45{
46public:
49 unsigned inWidth);
50 void releaseLine(unsigned y, std::span<Pixel> buf) override;
51
52private:
53 unsigned inWidth;
54};
55
56template<std::unsigned_integral Pixel, unsigned IN_WIDTH, typename SCALE>
58{
59public:
62 void releaseLine(unsigned y, std::span<Pixel> buf) override;
63};
64
65template<std::unsigned_integral Pixel>
67 : public StretchScalerOutputN<Pixel, 256, Scale_4on5<Pixel>>
68{
69public:
72};
73
74template<std::unsigned_integral Pixel>
76 : public StretchScalerOutputN<Pixel, 272, Scale_17on20<Pixel>>
77{
78public:
81};
82
83template<std::unsigned_integral Pixel>
85 : public StretchScalerOutputN<Pixel, 280, Scale_7on8<Pixel>>
86{
87public:
90};
91
92template<std::unsigned_integral Pixel>
94 : public StretchScalerOutputN<Pixel, 288, Scale_9on10<Pixel>>
95{
96public:
99};
100
101
102// class StretchScalerOutputBase
103
104template<std::unsigned_integral Pixel>
106 SDLOutputSurface& out,
107 PixelOperations<Pixel> pixelOps_)
108 : pixelOps(std::move(pixelOps_))
109 , output(out)
110{
111}
112
113template<std::unsigned_integral Pixel>
115{
116 for (auto& p : pool) {
118 }
119}
120
121template<std::unsigned_integral Pixel>
123{
124 return output.getWidth();
125}
126
127template<std::unsigned_integral Pixel>
129{
130 return output.getHeight();
131}
132
133template<std::unsigned_integral Pixel>
134std::span<Pixel> StretchScalerOutputBase<Pixel>::acquireLine(unsigned /*y*/)
135{
136 auto width = getWidth();
137 if (!pool.empty()) {
138 Pixel* buf = pool.back();
139 pool.pop_back();
140 return {buf, width};
141 } else {
142 unsigned size = sizeof(Pixel) * width;
143 return {static_cast<Pixel*>(MemoryOps::mallocAligned(64, size)),
144 width};
145 }
146}
147
148template<std::unsigned_integral Pixel>
149std::span<Pixel> StretchScalerOutputBase<Pixel>::releasePre(unsigned y, std::span<Pixel> buf)
150{
151 assert(buf.size() == getWidth());
152 pool.push_back(buf.data());
153 return output.acquireLine(y);
154}
155
156template<std::unsigned_integral Pixel>
157void StretchScalerOutputBase<Pixel>::releasePost(unsigned y, std::span<Pixel> dstLine)
158{
159 output.releaseLine(y, dstLine);
160}
161
162template<std::unsigned_integral Pixel>
164{
166 auto dstLine = output.acquireLine(y);
167 memset(dstLine, color);
168 output.releaseLine(y, dstLine);
169}
170
171
172// class StretchScalerOutput
173
174template<std::unsigned_integral Pixel>
176 SDLOutputSurface& out,
177 PixelOperations<Pixel> pixelOps_,
178 unsigned inWidth_)
179 : StretchScalerOutputBase<Pixel>(out, std::move(pixelOps_))
180 , inWidth(inWidth_)
181{
182}
183
184template<std::unsigned_integral Pixel>
185void StretchScalerOutput<Pixel>::releaseLine(unsigned y, std::span<Pixel> buf)
186{
187 auto dstLine = this->releasePre(y, buf);
188 auto dstWidth = dstLine.size();
189
190 auto srcWidth = (dstWidth / 320) * inWidth;
191 auto srcOffset = (dstWidth - srcWidth) / 2;
192 ZoomLine<Pixel> zoom(this->pixelOps);
193 zoom(buf.subspan(srcOffset, srcWidth), dstLine);
194
195 this->releasePost(y, dstLine);
196}
197
198
199// class StretchScalerOutputN
200
201template<std::unsigned_integral Pixel, unsigned IN_WIDTH, typename SCALE>
203 SDLOutputSurface& out,
204 PixelOperations<Pixel> pixelOps_)
205 : StretchScalerOutputBase<Pixel>(out, std::move(pixelOps_))
206{
207}
208
209template<std::unsigned_integral Pixel, unsigned IN_WIDTH, typename SCALE>
211{
212 auto dstLine = this->releasePre(y, buf);
213 auto dstWidth = dstLine.size();
214
215 auto srcWidth = (dstWidth / 320) * IN_WIDTH;
216 auto srcOffset = (dstWidth - srcWidth) / 2;
217 SCALE scale(this->pixelOps);
218 scale(buf.subspan(srcOffset, srcWidth), dstLine);
219
220 this->releasePost(y, dstLine);
221}
222
223
224// class StretchScalerOutput256
225
226template<std::unsigned_integral Pixel>
228 SDLOutputSurface& out,
229 PixelOperations<Pixel> pixelOps_)
231 out, std::move(pixelOps_))
232{
233}
234
235
236// class StretchScalerOutput272
237
238template<std::unsigned_integral Pixel>
240 SDLOutputSurface& out,
241 PixelOperations<Pixel> pixelOps_)
243 out, std::move(pixelOps_))
244{
245}
246
247
248// class StretchScalerOutput280
249
250template<std::unsigned_integral Pixel>
252 SDLOutputSurface& out,
253 PixelOperations<Pixel> pixelOps_)
255 out, std::move(pixelOps_))
256{
257}
258
259
260// class StretchScalerOutput288
261
262template<std::unsigned_integral Pixel>
264 SDLOutputSurface& out,
265 PixelOperations<Pixel> pixelOps_)
267 out, std::move(pixelOps_))
268{
269}
270
271
272// class StretchScalerOutputFactory
273
274template<std::unsigned_integral Pixel>
275std::unique_ptr<ScalerOutput<Pixel>> StretchScalerOutputFactory<Pixel>::create(
276 SDLOutputSurface& output,
277 PixelOperations<Pixel> pixelOps,
278 unsigned inWidth)
279{
280 switch (inWidth) {
281 case 320:
282 return std::make_unique<DirectScalerOutput<Pixel>>(output);
283 case 288:
284 return std::make_unique<StretchScalerOutput288<Pixel>>(
285 output, std::move(pixelOps));
286 case 280:
287 return std::make_unique<StretchScalerOutput280<Pixel>>(
288 output, std::move(pixelOps));
289 case 272:
290 return std::make_unique<StretchScalerOutput272<Pixel>>(
291 output, std::move(pixelOps));
292 case 256:
293 return std::make_unique<StretchScalerOutput256<Pixel>>(
294 output, std::move(pixelOps));
295 default:
296 return std::make_unique<StretchScalerOutput<Pixel>>(
297 output, std::move(pixelOps), inWidth);
298 }
299}
300
301// Force template instantiation.
302#if HAVE_16BPP
304#endif
305#if HAVE_32BPP
307#endif
308
309} // namespace openmsx
A frame buffer where pixels can be written to.
StretchScalerOutput256(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
StretchScalerOutput272(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
StretchScalerOutput280(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
StretchScalerOutput288(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
StretchScalerOutputBase & operator=(const StretchScalerOutputBase &)=delete
void fillLine(unsigned y, Pixel color) override
StretchScalerOutputBase(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
std::span< Pixel > acquireLine(unsigned y) final
std::span< Pixel > releasePre(unsigned y, std::span< Pixel > buf)
void releasePost(unsigned y, std::span< Pixel > dstLine)
const PixelOperations< Pixel > pixelOps
StretchScalerOutputBase(const StretchScalerOutputBase &)=delete
StretchScalerOutputN(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
void releaseLine(unsigned y, std::span< Pixel > buf) override
void releaseLine(unsigned y, std::span< Pixel > buf) override
StretchScalerOutput(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps, unsigned inWidth)
Stretch (or zoom) a given input line to a wider output line.
Definition: LineScalers.hh:243
constexpr mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
void * mallocAligned(size_t alignment, size_t size)
Definition: MemoryOps.cc:255
void freeAligned(void *)
Definition: MemoryOps.cc:285
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint32_t Pixel
STL namespace.
size_t size(std::string_view utf8)
static std::unique_ptr< ScalerOutput< Pixel > > create(SDLOutputSurface &output, PixelOperations< Pixel > pixelOps, unsigned inWidth)