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 override;
24 [[nodiscard]] unsigned getHeight() const override;
25 [[nodiscard]] Pixel* acquireLine(unsigned y) override;
26 void fillLine(unsigned y, Pixel color) override;
27
28protected:
29 [[nodiscard]] Pixel* releasePre(unsigned y, Pixel* buf);
30 void releasePost(unsigned y, Pixel* dstLine);
31
33
34private:
36 std::vector<Pixel*> pool;
37};
38
39template<std::unsigned_integral Pixel>
41{
42public:
45 unsigned inWidth);
46 void releaseLine(unsigned y, Pixel* buf) override;
47
48private:
49 unsigned inWidth;
50};
51
52template<std::unsigned_integral Pixel, unsigned IN_WIDTH, typename SCALE>
54{
55public:
58 void releaseLine(unsigned y, Pixel* buf) override;
59};
60
61template<std::unsigned_integral Pixel>
63 : public StretchScalerOutputN<Pixel, 256, Scale_4on5<Pixel>>
64{
65public:
68};
69
70template<std::unsigned_integral Pixel>
72 : public StretchScalerOutputN<Pixel, 272, Scale_17on20<Pixel>>
73{
74public:
77};
78
79template<std::unsigned_integral Pixel>
81 : public StretchScalerOutputN<Pixel, 280, Scale_7on8<Pixel>>
82{
83public:
86};
87
88template<std::unsigned_integral Pixel>
90 : public StretchScalerOutputN<Pixel, 288, Scale_9on10<Pixel>>
91{
92public:
95};
96
97
98// class StretchScalerOutputBase
99
100template<std::unsigned_integral Pixel>
102 SDLOutputSurface& out,
103 PixelOperations<Pixel> pixelOps_)
104 : pixelOps(std::move(pixelOps_))
105 , output(out)
106{
107}
108
109template<std::unsigned_integral Pixel>
111{
112 for (auto& p : pool) {
114 }
115}
116
117template<std::unsigned_integral Pixel>
119{
120 return output.getWidth();
121}
122
123template<std::unsigned_integral Pixel>
125{
126 return output.getHeight();
127}
128
129template<std::unsigned_integral Pixel>
131{
132 if (!pool.empty()) {
133 Pixel* buf = pool.back();
134 pool.pop_back();
135 return buf;
136 } else {
137 unsigned size = sizeof(Pixel) * output.getWidth();
138 return static_cast<Pixel*>(MemoryOps::mallocAligned(64, size));
139 }
140}
141
142template<std::unsigned_integral Pixel>
144{
145 pool.push_back(buf);
146 return output.acquireLine(y);
147}
148
149template<std::unsigned_integral Pixel>
151{
152 output.releaseLine(y, dstLine);
153}
154
155template<std::unsigned_integral Pixel>
157{
158 Pixel* dstLine = output.acquireLine(y);
160 memset(dstLine, output.getWidth(), color);
161 output.releaseLine(y, dstLine);
162}
163
164
165// class StretchScalerOutput
166
167template<std::unsigned_integral Pixel>
169 SDLOutputSurface& out,
170 PixelOperations<Pixel> pixelOps_,
171 unsigned inWidth_)
172 : StretchScalerOutputBase<Pixel>(out, std::move(pixelOps_))
173 , inWidth(inWidth_)
174{
175}
176
177template<std::unsigned_integral Pixel>
179{
180 Pixel* dstLine = this->releasePre(y, buf);
181
182 unsigned dstWidth = StretchScalerOutputBase<Pixel>::getWidth();
183 unsigned srcWidth = (dstWidth / 320) * inWidth;
184 unsigned srcOffset = (dstWidth - srcWidth) / 2;
185 ZoomLine<Pixel> zoom(this->pixelOps);
186 zoom(buf + srcOffset, srcWidth, dstLine, dstWidth);
187
188 this->releasePost(y, dstLine);
189}
190
191
192// class StretchScalerOutputN
193
194template<std::unsigned_integral Pixel, unsigned IN_WIDTH, typename SCALE>
196 SDLOutputSurface& out,
197 PixelOperations<Pixel> pixelOps_)
198 : StretchScalerOutputBase<Pixel>(out, std::move(pixelOps_))
199{
200}
201
202template<std::unsigned_integral Pixel, unsigned IN_WIDTH, typename SCALE>
204{
205 Pixel* dstLine = this->releasePre(y, buf);
206
207 unsigned dstWidth = StretchScalerOutputBase<Pixel>::getWidth();
208 unsigned srcWidth = (dstWidth / 320) * IN_WIDTH;
209 unsigned srcOffset = (dstWidth - srcWidth) / 2;
210 SCALE scale(this->pixelOps);
211 scale(buf + srcOffset, dstLine, dstWidth);
212
213 this->releasePost(y, dstLine);
214}
215
216
217// class StretchScalerOutput256
218
219template<std::unsigned_integral Pixel>
221 SDLOutputSurface& out,
222 PixelOperations<Pixel> pixelOps_)
224 out, std::move(pixelOps_))
225{
226}
227
228
229// class StretchScalerOutput272
230
231template<std::unsigned_integral Pixel>
233 SDLOutputSurface& out,
234 PixelOperations<Pixel> pixelOps_)
236 out, std::move(pixelOps_))
237{
238}
239
240
241// class StretchScalerOutput280
242
243template<std::unsigned_integral Pixel>
245 SDLOutputSurface& out,
246 PixelOperations<Pixel> pixelOps_)
248 out, std::move(pixelOps_))
249{
250}
251
252
253// class StretchScalerOutput288
254
255template<std::unsigned_integral Pixel>
257 SDLOutputSurface& out,
258 PixelOperations<Pixel> pixelOps_)
260 out, std::move(pixelOps_))
261{
262}
263
264
265// class StretchScalerOutputFactory
266
267template<std::unsigned_integral Pixel>
268std::unique_ptr<ScalerOutput<Pixel>> StretchScalerOutputFactory<Pixel>::create(
269 SDLOutputSurface& output,
270 PixelOperations<Pixel> pixelOps,
271 unsigned inWidth)
272{
273 switch (inWidth) {
274 case 320:
275 return std::make_unique<DirectScalerOutput<Pixel>>(output);
276 case 288:
277 return std::make_unique<StretchScalerOutput288<Pixel>>(
278 output, std::move(pixelOps));
279 case 280:
280 return std::make_unique<StretchScalerOutput280<Pixel>>(
281 output, std::move(pixelOps));
282 case 272:
283 return std::make_unique<StretchScalerOutput272<Pixel>>(
284 output, std::move(pixelOps));
285 case 256:
286 return std::make_unique<StretchScalerOutput256<Pixel>>(
287 output, std::move(pixelOps));
288 default:
289 return std::make_unique<StretchScalerOutput<Pixel>>(
290 output, std::move(pixelOps), inWidth);
291 }
292}
293
294// Force template instantiation.
295#if HAVE_16BPP
297#endif
298#if HAVE_32BPP
300#endif
301
302} // 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)
unsigned getHeight() const override
StretchScalerOutputBase & operator=(const StretchScalerOutputBase &)=delete
void fillLine(unsigned y, Pixel color) override
Pixel * acquireLine(unsigned y) override
Pixel * releasePre(unsigned y, Pixel *buf)
StretchScalerOutputBase(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
void releasePost(unsigned y, Pixel *dstLine)
unsigned getWidth() const override
const PixelOperations< Pixel > pixelOps
StretchScalerOutputBase(const StretchScalerOutputBase &)=delete
StretchScalerOutputN(SDLOutputSurface &out, PixelOperations< Pixel > pixelOps)
void releaseLine(unsigned y, Pixel *buf) override
void releaseLine(unsigned y, 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:240
constexpr mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
void * mallocAligned(size_t alignment, size_t size)
Definition: MemoryOps.cc:254
void freeAligned(void *)
Definition: MemoryOps.cc:284
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint32_t Pixel
constexpr int SCALE
Definition: ArkanoidPad.cc:24
STL namespace.
size_t size(std::string_view utf8)
static std::unique_ptr< ScalerOutput< Pixel > > create(SDLOutputSurface &output, PixelOperations< Pixel > pixelOps, unsigned inWidth)